观察者模式(Observer Pattern)也称发布订阅模式,它是一种在项目中经常使用的模式。
定义:
- 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
观察者模式的类图如下所示。
观察者模式具体有以下4个角色。
- 抽象主题(Subject)角色:又称为“被观察者”,可以增加和删除观察者对象。
- 抽象观察者(Observer)角色:为所有具体观察者定义一个接口,在得到主题的通知时更新自己。
- 具体主题(Concrete Subject)角色:又称“具体被观察者”,它将有关状态存入具体观察者对象,当它改变时,给所有登记过的观察者发出通知。
- 具体观察者(Concrete Observer)角色:实现抽象观察者所有的更新接口,以便使自身状态与主题状态相协调。
Subject.java
public interface Subject { // 登记一个新的观察者 public void attach(Observer obs); // 删除一个登记过的观察者 public void detach(Observer obs); // 通知所有登记过的观察者对象 public void notifyObserver(); }
Observer.java
public interface Observer { // 更新方法 public void update(); }
ConcreteSubject.java
public class ConcreteSubject implements Subject { private Vector<Observer> obsVector = new Vector<Observer>(); @Override public void attach(Observer obs) { obsVector.add(obs); } @Override public void detach(Observer obs) { obsVector.remove(obs); } @Override public void notifyObserver() { for (Observer obs : obsVector) { obs.update(); } } public Enumeration<Observer> observers() { return obsVector.elements(); } // 业务方法,改变状态 public void change() { this.notifyObserver(); } }
ConcreteObserver.java
public class ConcreteObserver implements Observer { @Override public void update() { System.out.println("收到通知,并进行处理"); } }
Client.java
public class Client { public static void main(String[] args) { // 创建一个主题对象(被观察者) ConcreteSubject subject = new ConcreteSubject(); // 创建一个观察者 Observer obs = new ConcreteObserver(); // 登记观察者 subject.attach(obs); // 改变状态 subject.change(); } }
优点:
- 观察者与被观察者之间是抽象耦合,它们属不同的抽象化层次,且都很容易扩展。
- 支持广播通信。被观察者向所有登记过的观察者发出通知,这就是一个触发机制,形成一个触发链。
缺点:
- 一个主题有多个直接或间接观察者,通知所有观察者会花费很多时间,且开发和调试都比较困难。
- 如果主题之间有循环依赖,被观察者会触发它们之间进行循环调用,导致系统崩溃。
- 如果对观察者的通知是通过另外的线程进行异步投递,系统必须保证投递的顺序执行。
- 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有提供相应的机制使观察者知道所观察的对象是如何发生变化。
应用场景:
- 关联行为场景。
- 事件多级触发场景。
- 跨系统的消息交换场景,如消息队列的处理机制。
注意事项:
- 广播链的问题一个观察者可以有双重身份,既是观察者又是被观察者,广播链一旦建立,逻辑就比较复杂,可给你的维护性非常差。一般在一个观察者模式中最多出现一个对象既是观察者也是被观察者,这样消息最多转发一次(传递两次)较易控制。
- 异步处理的问题。异步处理就要考虑线程安全和队列问题。
引用:
青岛东合信息技术有限公司 . 设计模式(Java版) . 电子工业出版社,2012,149-152.