设计模式-观察者模式
观察者模式(行为型模式)
- 定义
观察者模式(Observer),定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。[DP]
自己的理解:观察者模式又叫发布-订阅(Publish/Subscribe)模式,通知者作为发布方,多个观察者作为订阅方,多个观察者被添加进通知者,当发生状态变化时,通知者会通知所有观察者(观察者没有被删除的情况下)
- 特点
- 所有添加进被观察者的观察者都会收到被观察者的通知
- 被观察者可以删除和添加观察者
- 结构
Observer:抽象观察者
ConcreteObserver:具体观察者(订阅者)
Subject:抽象被观察者(抽象通知者)
ConcreteSubject:具体通知者(发布者)
- 代码
例子:公司职员作为观察者,老板作为通知者,当老板回来的时候,职员需要关闭不是工作得事情,开始工作
/** * @ Author :fonxi * @ Date :2019/5/28 15:23 * @ Description:抽象观察者 */ public abstract class Observer { protected String name; protected Subject sub; public Observer(String name,Subject sub){ this.name = name; this.sub = sub; } public abstract void update(); }
具体职员
/** * @ Author :fonxi * @ Date :2019/5/28 15:36 * @ Description:具体观察者 看股票行情的职员 */ public class StockObserver extends Observer{ public StockObserver(String name, Subject sub) { super(name, sub); } @Override public void update() { System.out.printf("%n%s %s 关闭股票行情,继续工作",sub.getSubjectState(),name); } }
/** * @ Author :fonxi * @ Date :2019/5/28 15:49 * @ Description:具体观察者 看NBA的职员 */ public class NBAObserver extends Observer { public NBAObserver(String name, Subject sub) { super(name, sub); } @Override public void update() { System.out.printf("%n%s %s NBA直播,继续工作",sub.getSubjectState(),name); } }
抽象通知者
/** * @ Author :fonxi * @ Date :2019/5/28 15:23 * @ Description:通知者接口 */ public interface Subject { void attach(Observer observer); void detach(Observer observer); void notifying(); String getSubjectState(); }
具体通知者BOSS
/** * @ Author :fonxi * @ Date :2019/5/28 15:29 * @ Description:具体通知者 */ public class Boss implements Subject { private String action; //同事列表 private List<Observer> observerList = new ArrayList<>(); //添加观察者 @Override public void attach(Observer observer) { observerList.add(observer); } //删除观察者 @Override public void detach(Observer observer) { observerList.remove(observer); } //通知每一个观察者 @Override public void notifying() { observerList.forEach(e->e.update()); } @Override public String getSubjectState() { return getAction(); } public String getAction() { return action; } public void setAction(String action) { this.action = action; } }
客户端调用类
/** * @ Author :fonxi * @ Date :2019/5/28 15:20 * @ Description:客户端调用类 */ public class TestController { public void print(){ //老板 Boss boss = new Boss(); //看股票的同事 StockObserver colleague1 = new StockObserver("魏关姹",boss); //看NBA的同事 NBAObserver colleague2 = new NBAObserver("易管查",boss); boss.attach(colleague1); boss.attach(colleague2); //老板回来 boss.setAction("老板回来了"); //发出通知 boss.notifying(); } }
输出结果
老板回来了 魏关姹 关闭股票行情,继续工作 老板回来了 易管查 NBA直播,继续工作
被添加进通知者的观察者都会收到通知者发出的通知。
- 使用场景
- 发布订阅
- 优缺点
优点:
- 观察者和被观察者(通知者)是抽象耦合的,观察者容易扩展
- 对象之间保持搞得协作,当被观察者发生状态变化,所有观察者都会被通知到,做出相应的动作
缺点:
- 如果观察者太多,逐一通知可能会花费很多的时间和资源
- 某一观察者发生错误,会导致整个程序卡住
- 总结
观察者模式适用于多个对象都因为一个对象的状态变化而统一做出相应的动作,观察者过多可以通过异步的方式。抽象观察者类也可以改用接口。