观察者模式
定义:定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
通常观察者模式包括四个角色:
- Subject,抽象主题类,定义公共管理观察者的接口。
- ConcreteSubject,具体主题类,实现抽象主题接口,内部存储被订阅的观察者列表。
- Observer,抽象观察者,定义公共接口。
- ConcreteObserver,具体观察者,实现抽象观察者接口。具体主题类会通知到每个具体观察者。
观察者模式就比如订阅报纸,ConcreteSubject相当报社,如果哪个人(也就是ConcreteObserver)要订阅报纸,就要向报社申请(subscribe),报社一有最新的报纸就会通知(notify)每一个观察者(update),如果我想不想看了,可以找报社取消订阅(unsubscribe)。在实际开发当中,观察者模式Subject大多数情况是不需要的,直接具体主题类管理通知观察者。
代码示例
抽象观察者
public interface Observer {
void update();
}
各个具体观察者
public class Programmer implements Observer{
public void update() {
System.out.println("程序员收到了一份报纸");
}
}
public class Police implements Observer{
public void update() {
System.out.println("警察收到了一份报纸");
}
}
具体主题类
public class Newspaper {
private List<Observer> observers = new ArrayList<Observer>();
public void subject(Observer observer) {//订阅报纸
observers.add(observer);
}
public void unsubject(Observer observer) {//取消订阅
observers.remove(observer);
}
public void notifyObserver(){//通知所有观察者
for(Observer o : observers){
o.update();
}
}
}
客户端
Newspaper newspaper = new Newspaper();
newspaper.subject(new Police());
newspaper.subject(new Programmer());
newspaper.notifyObserver();
输出为
警察收到了一份报纸
程序员收到了一份报纸
很显然,观察者模式减少了客户端对观察者们的依赖,甚至可以在客户端与各观察者进行通信。Java也有自带的观察者类,在java.util包下有一个Observable类和Observer接口。Observable内部原理跟上面的ConcreteSubject几乎一样,只不过加了同步块还有些方法。
总的来说,观察者模式用处有很多,JavaSwing大多都采用观察者模式,鼠标点击控件,系统就会通知该控件的点击事件响应。使用观察者模式大大分离了依赖,降低耦合,实际开发必须了解观察者模式。不足之处望指教。