简介
观察者模式(Observer Pattern)隶属于设计模式中的行为型模式。通过发布事件来将状态变化与处理逻辑解耦开来,可以拥有更好的可扩展性和可维护性。
观察者模式,又叫发布-订阅模式,通过定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于他的对象都会得到通知。
观察者模式是典型的生产者消费者问题模式,被观察的对象状态改变后产生事件,对此事件感兴趣的观察者可以做出某些行为。
观察者模式的角色可分为两类,总共四种角色,分别是:
在Java 中,jdk 自带了观察者模式需要的接口,分别是 被观察者Observable
, 抽象观察接口 Observer
,遗憾的是Java 中的被观察者Observable
是一个类而不是接口,在需要继承的场景中就无法使用它提供的功能了。
消息队列可以说是观察者模式的高级别应用了,直接提升到了中间件的高度,不过我们还是在具体代码里来说明这个模式。
以前在写单一职责原则时举过登录成功之后使用观察者模式来通知各方,以实现登录主逻辑和登录后的记录、短信通知等操作解耦开来,在写开闭原则的时候也举了一个订单付款后的例子,也是观察者模式。有兴趣的可以去看一下。
今天我们使用图书馆来举例,假设图书馆提供借书服务,但是一本书可能有多个人来借却只能借给一个人,其他人就只能等前一个借书的人还了之后再来借,但是让人一遍遍来询问就太耗费时间了,我们通过观察者模式将书被还回来的事件通知给感兴趣的借书人,他们就可以在收到通知后来图书馆借书了。
这里我们直接使用 Java 提供的功能和接口
import java.util.Observable;
import java.util.Observer;
/**
* 借阅的学生
* @author dylan
*/
public class Student implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println(arg + " 还回来了");
}
}
/**
* 图书馆
*/
public class Library extends Observable {
private Set<String> books = new HashSet<>(Arrays.asList("基业长青", "大象", "构建之法", "Unix 环境编程"));
/**
* 借出书籍
*
* @param book 被借的书
*/
public void lend(String book) {
books.remove(book);
}
/**
* 书籍还回来
*
* @param book 被还的书
*/
public void returnBack(String book) {
books.add(book);
// 通知所有等待的借书人
notifyObservers(book);
}
public static void main(String[] args) {
Student lily = new Student();
Student adam = new Student();
Library library = new Library();
library.addObserver(lily);
library.addObserver(adam);
library.setChanged();
library.lend("大象");
//两个学生都收到了书送还的通知
library.returnBack("大象");
}
}
注意在使用 Java 提供的 Observable
类时,如果需要将事件通知出去,需要调用 setChange
方法
onChangeListner