观察者模式实例解析
概述
观察者模式,顾名思义就是“观察主题状态变更”,我们接触到的ServletContextListener、ApplicationListener都是使用这种开发模式。从代码结构层面可以描述为主题对象保存所有关心此主题状态的观察者对象的引用,当状态变更时通知所有观察者对象。
类图
【运行原理剖析】
Subject持有对Observer对象的引用,Observer的具体类(ConcreteObserver)持有对Subject具体类(ConcreteSubject)的引用,首先创建ConcreteSubject对象concreteSubject,在用此对象初始化创建ConcreteObserver对象A、B、C,这样就有了三个观察者,在通过concreteSubject的attach方法将ConcreteObserver对象A、B、C进行注册。这样当concreteSubject的状态subjectState改变时就可以通过调用notify方法通知所有的观察者注册对象,观察者则选择性的处理自己感兴趣的状态。当然也可以考虑下双向监听,互为主题和观察者,多主题多观察者的情况。
实例
观察者类
【Observer.java】
publicabstractclassObserver {
publicabstractvoid update();
}
【ConcreteObserver.java】
publicclassConcreteObserver extends Observer{
private String obverserState;
private String name;
private ConcreteSubject concreteSubject;
public ConcreteSubjectgetConcreteSubject() {
returnconcreteSubject;
}
publicvoidsetConcreteSubject(ConcreteSubject concreteSubject) {
this.concreteSubject =concreteSubject;
}
public ConcreteObserver(ConcreteSubjectconcreteSubject,String name){
this.concreteSubject =concreteSubject;
this.name = name;
}
@Override
publicvoid update() {
this.obverserState = concreteSubject.getSubjectState();
System.out.println("The obverser`s state of " + this.name + " is " + this.obverserState);
}
}
主题类
【Subject.java】
publicabstractclassSubject {
protectedList<Observer> observerList = newArrayList<Observer>();
publicvoid attach(Observerobserver){
observerList.add(observer);
}
publicvoid dettach(Observer observer){
observerList.remove(observer);
}
publicvoid publish(){
for(Observer o:observerList){
o.update();
}
}
}
【ConcreteSubject.java】
publicclassConcreteSubject extends Subject{
private String subjectState;
public StringgetSubjectState() {
returnsubjectState;
}
publicvoid setSubjectState(StringsubjectState) {
this.subjectState = subjectState;
}
}
测试类
【TestDesignPattern.java】
publicclassTestDesignPattern {
publicstaticvoid main(String[] args){
ConcreteSubjectconcreteSubject = new ConcreteSubject();
concreteSubject.attach(newConcreteObserver(concreteSubject, "ObserverA"));
concreteSubject.attach(newConcreteObserver(concreteSubject, "ObserverB"));
concreteSubject.attach(newConcreteObserver(concreteSubject, "ObserverC"));
concreteSubject.setSubjectState("Ready");
concreteSubject.publish();
}
}
运行结果
总结
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
缺点
依赖关系并未完全解除,抽象主题仍然依赖抽象观察者。(可以用代理模式解决,后续博文介绍此内容)
适用场景
Ø 当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
Ø 一个抽象类型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。