观察者模式
一、定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
观察者模式的通用类图
Subject是被观察者,它必须能够动态地增加、取消观察者。它一般仅仅完成管理观察者并通知观察者的职责;
Observer是观察者;concreteSubject是具体的观察者,定义被观察者自己的逻辑,同时定义对那些事件进行通知;ConcreteObserver是具体的观察者。
观察者模式的通用类图
-
被观察者
public abstract class Subject { //定义一个观察者数组 private Vector<Observer> obsVector = new Vector<Observer>(); //增加一个观察者 public void addObserver(Observer o){ this.obsVector.add(o); } //删除一个观察者 public void delObserver(Observer o){ this.obsVector.remove(o); } //通知所有观察者 public void notifyObservers(){ for(Observer o:this.obsVector){ o.update(); } } }
-
具体被观察者
public class ConcreteSubject extends Subject { //具体的业务 public void doSomething(){ /* * do something */ super.notifyObservers(); } }
-
观察者
public interface Observer { //更新方法 public void update(); }
-
具体观察者
public class ConcreteObserver implements Observer { //实现更新方法 public void update() { System.out.println("接收到信息,并进行处理!"); } }
-
场景类
public class Client { public static void main(String[] args) { //创建一个被观察者 ConcreteSubject subject = new ConcreteSubject(); //定义一个观察者 Observer obs= new ConcreteObserver(); //观察者观察被观察者 subject.addObserver(obs); //观察者开始活动了 subject.doSomething(); } }
二、观察者模式的优点
-
观察者和被观察者之间是抽象耦合的
抽象耦合的设计使得不管是增加观察者还是增加被观察则都非常容易扩展
-
建立一套触发机制
实现触发链,将各个单一职责串联成复杂的逻辑关系
三、观察者模式的缺点
当有多个观察者时,要注意通知的方式,在java中消息的通知默认是顺序执行的,一个观察者卡主,会影响整体的执行效率,这种情况下一般会考虑采用异步的方式。
四、观察者模式的使用场景
-
关联行为场景
关联行为要是可拆分的,而不是“组合”关系
-
事件多级触发场景
-
跨系统的消息交互场景,如消息队列的处理机制
注意:观察者模式要解决两个问题
广播链的问题
一个观察者可以有双重身份,既是观察者,也是被观察者,此时如果广播链建立,逻辑就变得复杂,可维护性非常差。根据经验建议,在一个观察者模式中最多出现一个对象既是观察者也是被观察者
异步处理问题
当消息分发用异步模式时,要考虑线程安全和队列的问题;