介绍
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。
类图说明
Observer:观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
ConcreteObserver:具体的观察者对象,如类图中的ConcreteObserver1和ConcreteObserver2。
Subject:定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类
或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。如类图中定义了attach()添加观察者方法,deltach()删除观察者方法,notifyObservers()通知所有观察者方法。
ObserverPattern:定义一个调用者。
代码示例
文件结构如下:
代码示例如下:
public interface Observer {
void update();
}
public class ConcreteObserver1 implements Observer {
@Override
public void update() {
System.out.println("ConcreteObserver1 收到通知");
}
}
public class ConcreteObserver2 implements Observer {
@Override
public void update() {
System.out.println("ConcreteObserver2 收到通知");
}
}
public class Subject {
private List<Observer> list = new ArrayList<Observer>();
public void attach(Observer observer){
list.add(observer);
}
public void deltach(Observer observer){
list.remove(observer);
}
public void notifyObservers(){
list.forEach(Observer::update);
}
}
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new Subject();
ConcreteObserver1 concreteObserver1 = new ConcreteObserver1();
ConcreteObserver2 concreteObserver2 = new ConcreteObserver2();
// 注册两个观察者
subject.attach(concreteObserver1);
subject.attach(concreteObserver2);
// 被观察者通知
subject.notifyObservers();
}
}
运行结果如下:
应用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度
- 一个对象必须通知其他对象,而并不知道这些对象是谁
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制
优缺点
优点
- 观察者和被观察者是抽象耦合的
- 建立一套触发机制
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化