意图:
定义对象间地一种一对多地依赖关系,当一个对象地状态发生改变时,所有对于依赖于它的对象都得到通知并被自动更新。别名:
依赖(Dependents), 发布-订阅(Publish-Subsribe)动机:
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维护一致性而是各类紧密耦合,这样降低了它们的可重用性。适用性:
在以下任一情况下可以使用观察者模式:
a. 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
b. 当一个对象必须通知其它对象,而它有不能假定其他对象是谁。换言之,你不希望这些对象是紧密耦合的。结构:
参与者:
a. Subject:
目标知道它的观察者。可以有多个观察者观察同一个目标。
提供注册和删除观察者对象的接口。
b. Observer:
为那些在目标发生改变时需获得通知的对象定义一个跟新接口。
c. ConcreteSubject:
将有关状态 存入各ConcreteObserver
当它的状态发生改变时,向它的各个观察者发生通知。
d. ConcreteObserver:
维护一个指向ConcreteSubject对象的引用。
存储有关状态,这些状态应与目标的状态保持一致。
实现Observer的更新接口以使自身状态与目标的状态保持一致。协作:
效果:
a. 目标和观察者间的抽象耦合
b. 支持广播通信
c. 意外的更新实现:
a. 创建目标到其观察者之间的映射
b. 观察多个目标
c. 谁触发更新
d. 对已删除目标悬挂引用
e. 在发出通知前确保目标的状态自身是一致的
f. 避免特定于观察者的更新协议–推/拉模式
g. 显式地指定感兴趣的改变
h. 封装复杂的更新语义
i. 结合目标类和观察者代码示例:
public interface Observer {
void update();
}
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notify2();
}
public class ConcreteSubject implements Subject {
private int state;
private List<Observer> observers = new ArrayList<>();
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notify2() {
for (Observer observer : observers) {
observer.update();
}
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notify2();
}
}
public class ConcreteObserver implements Observer{
private int observerState;
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
observerState = subject.getState();
System.out.println("Observer state update: " + observerState);
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver(subject);
ConcreteObserver observer2 = new ConcreteObserver(subject);
subject.setState(10);
subject.setState(20);
subject.detach(observer1);
subject.detach(observer2);
}
}
已知应用:
相关模式:
Mediator:通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。
Singleton: ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。