Java 设计模式之观察者模式
一、定义
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
主要角色:
抽象主题(抽象被观察者): 它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
具体主题(具体被观察者):它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
抽象观察者:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
二、代码实现
举例:张三,李四两个人都关注了某一个微信公共号,当公众号发送文章时,张三和李四都会收到推送,其中公众号就是被观察者,张三李四为观察者。
抽象主题:抽象被观察者
interface Subject { //绑定观察者 void attach(Observer observer); //解绑观察者 void detach(Observer observer); //更新 void update(String msg); }
具体主题:具体被观察者(微信公众号)
class SubscriptionSubject implements Subject { //存储观察者 private ListobserverList = new ArrayList<>(); @Override public void attach(Observer observer) { observerList.add(observer); } @Override public void detach(Observer observer) { observerList.remove(observer); } @Override public void update(String msg) { for (Observer observer : observerList){ observer.update(msg); } } }
抽象观察者:
interface Observer { void update(String msg); }
具体观察者:微信用户
class WechatUser implements Observer { private String name; public WechatUser(String name) { this.name = name; } @Override public void update(String msg) { System.out.println(name+"收到了推送:"+msg); } }
使用:
public static void main(String[] args) { //公众号 SubscriptionSubject subject = new SubscriptionSubject(); //张三 WechatUser zhangsan = new WechatUser("张三"); WechatUser lisi = new WechatUser("李四"); //订阅 subject.attach(zhangsan); subject.attach(lisi); //更新 subject.update("Java从入门到放弃"); }
输出:
张三收到了推送:Java从入门到放弃 李四收到了推送:Java从入门到放弃
三、总结
优点:
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
目标与观察者之间建立了一套触发机制。
缺点:
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
使用场景:
对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。