1.观察者(Observer)模式的定义
- 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
- 这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
2.观察者模式主要优缺点
优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 目标与观察者之间建立了一套触发机制。
缺点:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
3.观察者模式的主要角色
- 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。
4.观察者模式的结构图
5.观察者模式的实现,以股票为例
- 定义抽象目标类
package com.lw.designpattern.observer; import java.util.ArrayList; import java.util.List; /** * @Classname Subject * @Description 定义抽象目标类 * @Author lw * @Date 2020-01-09 08:53 */ public abstract class Subject { /** * 定义观察者集合,用于管理观察者 */ public List<Observer> observers = new ArrayList<>(); /** * 向观察者集合中添加观察者对象 * * @param observer */ public void add(Observer observer) { observers.add(observer); } /** * 向观察者集合中删除观察者对象 * * @param observer */ public void remove(Observer observer) { observers.remove(observer); } /** * 通知观察者抽象方法,股票上涨 */ public abstract void increase(); /** * 通知观察者抽象方法,股票下跌 */ public abstract void decrease(); }
- 定义具体目标类,继承Subject抽象目标类
package com.lw.designpattern.observer; /** * @Classname PingAnSecurities * @Description 具体目标类,平安证券 * @Author lw * @Date 2020-01-09 08:59 */ public class PingAnSecurities extends Subject { @Override public void increase() { System.out.println("平安证券股票上涨了。。。。。。"); for (Observer observer : observers) { observer.happy(); } } @Override public void decrease() { System.out.println("平安证券股票下跌了。。。。。。"); for (Observer observer : observers) { observer.terrible(); } } }
- 定义抽象观察者接口
package com.lw.designpattern.observer; /** * @Classname Observer * @Description 抽象观察者 * @Author lw * @Date 2020-01-09 09:01 */ public interface Observer { void happy(); void terrible(); }
- 定义具体观察者(张三股民),实现Observer接口
package com.lw.designpattern.observer; /** * @Classname ZsStockholder * @Description 具体观察者-张三股民 * @Author lw * @Date 2020-01-09 09:04 */ public class ZsStockholder implements Observer { @Override public void happy() { System.out.println("张三股民开心"); } @Override public void terrible() { System.out.println("张三股民难受"); } }
- 定义具体观察者(李四股民),实现Observer接口
package com.lw.designpattern.observer; /** * @Classname LsStockholder * @Description 具体观察者-李四股民 * @Author lw * @Date 2020-01-09 09:04 */ public class LsStockholder implements Observer { @Override public void happy() { System.out.println("李四股民开心"); } @Override public void terrible() { System.out.println("李四股民难受"); } }
- 单元测试
/** * 观察者模式 */ @Test public void testObserver() { // 创建目标类(平安证券) Subject subject = new PingAnSecurities(); // 添加张三和李四股民观察者 subject.add(new ZsStockholder()); subject.add(new LsStockholder()); // 股票上涨 subject.increase(); // 股票下跌 subject.decrease(); }
打印结果
6.观察者模式的应用场景
- 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。