设计模式之观察者模式
观察者模式(Observer),其含义是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式也称为发布-订阅模式。将一个系统分割一系列相互作用的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。 观察者模式的关键对象是目标和观察者,一个目标可以有任意数目的依赖它的观察者,一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,灭个观察者都将查询目标以使其状态与目标的状态同步。目标是通知的发布者,它发出通知时并不需知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。
其适用性:
当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用,
当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变,
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
其结构图:
每个subject维护以个Observer的列表,意思是一个目标类可以被多个观察者观察,其可以绑定或解除一个observer;而observer类必须具有在subject改变时,接收到通知后更新相关信息(如状态)。实现如下:
package org.designpattern.behavioral.observer;
import java.util.List;
public abstract class Subject {
protected String state;
protected List<Observer> observers;
public abstract void attach(Observer observer);
public abstract void detach(Observer observer);
public abstract void notice();
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
每个Subject的子类,在通知改变时会通知所有观察自己的观察者,具体代码可参考本博客的github。
在一个Observer抽象基类里,会有指定自己要观察的Subject实例,也就是具有该属性,通过记录它的状态来实现。下面是Observer的一个具体子类,其更新操作是记录目标的状态:
package org.designpattern.behavioral.observer;
public ConcreteObserverA(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update(Subject subject) {
//To change body of implemented methods use File | Settings | File Templates.
this.setState(subject.getState());
}
}
客户端测试类较为简单:
package org.designpattern.behavioral.observer;
public static void main(String[] args) {
Subject subject = new ConcreteSubject();
Observer obsvrA = new ConcreteObserverA(subject);
Observer obsvrB = new ConcreteObserverB(subject);
subject.setState("red");
System.out.println(obsvrA.getState());
System.out.println(obsvrB.getState());
subject.notice();
System.out.println(obsvrA.getState());
System.out.println(obsvrB.getState());
}
}
第一次观察者的state都是null,在获取subject通知后,再次获取state就是变成了red。
观察者模式在书中的例子是关于数据显示问题,这样根据需要做粗不同的显示图。观察者模式和协调者模式一样都是定义一对多的对象关系,此模式可使得对象之间进行同步通信。该模式可与单例模式一起构建一个更改管理其对象,经典的MVC思想非常类似观察者模式,只是观察的对象不同,其是视图页面来观察数据。