一、观察者模式概述
观察者模式是使用频率较高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。
定义:
观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象发生改变时其相关依赖对象借得到通知而被自动更新。
观察者模式的别名有发布-订阅(Publish-Subscribe)模式、模型-试图(Model-view——模式、源-监听器(Source-Listener)模式、从属者(Dependents)模式。
二、观察者模式的结构和实现
2.1 观察者模式的结构
观察者模式包含以下4个角色:
- Subject(目标):目标又称为主题,它是指被观察的对象。
- ConcreteSubject(具体目标):具体目标是目标的子类。它通常包含有经常发生改变的数据,当它的状态发生改变时将向它的各个观察者发出通知。
- Observer(观察者):观察者将对观察目标的改变而做出反应。
- ConcreteObserver(具体观察者):具体观察者是观察者的子类,实现在观察者中声明的更新数据的方法。
2.2 观察者模式的实现
JDK对观察者模式提供了支持,在JDK的java.util包中提供了Observable类以及Observer接口,其中Observable类充当抽象观察目标类,Observer接口充当抽象观察者。
下面通过使用JDK提供的类和接口来实现观察者模式的案例。
//具体的目标类
import java.math.BigDecimal;
import java.util.Observable;
/**
* 股票,充当具体的观察目标类
* 继承jdk自带的抽象观察目标类
*/
public class Stock extends Observable {
//股票价格
private BigDecimal price;
public Stock(BigDecimal price){
this.price = price;
}
/**
* 模拟股票涨跌情况,如果有超过涨跌幅达到5%及其以上,
* 就通知购买了股票的股民,并告知当前股票价格情况
*
* @param scope 涨跌幅,单位%,比如scope=0.02,就是涨了2%
*/
public void advancesVersusDeclines(BigDecimal scope) {
price = price.multiply(scope).add(price);
if (scope.doubleValue() >= 0.05) {
super.setChanged();
super.notifyObservers(price);
}
}
public BigDecimal getPrice() {
return price;
}
}
//具体的观察者
import java.util.Observable;
import java.util.Observer;
/**
* 股民,充当具体观察对象
* 继承jdk自带的抽象观察者
*/
public class Investor implements Observer {
private String name;
public Investor(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "你好,股票涨跌幅超过5%,当前股票价格为:" + arg);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//客户端
public class Client {
public static void main(String[] args) {
/**
* 案例需求描述:
* 某股票软件需要提供以下功能:
* 当股票购买者所购买的某只股票的价格变化幅度达到5%,系统将自动发送通知(包括新价格)给购买该股票的股民。
* 试适用观察者模式设计并实现该功能。
*/
//发布一个新的股票,并设置股票初始价格
Stock stock = new Stock(new BigDecimal("10"));
//定义股民
Investor zhangsan = new Investor("张三");
Investor lisi = new Investor("李四");
Investor wangwu = new Investor("王五");
//股名购买了这只股票
stock.addObserver(zhangsan);
stock.addObserver(lisi);
stock.addObserver(wangwu);
//模拟股票实时变化情况
stock.advancesVersusDeclines(new BigDecimal("0.02"));
stock.advancesVersusDeclines(new BigDecimal("0.0345"));
stock.advancesVersusDeclines(new BigDecimal("0.0512"));
stock.advancesVersusDeclines(new BigDecimal("0.0312"));
}
}
三、观察者模式的优缺点和适用环境
3.1 观察者模式的优点
- 实现表示层和数据逻辑层的分离;
- 在观察目标和观察者之间建立一个抽象的耦合;
- 支持广播通信且符合开闭原则;
3.2 观察者模式的缺点
- 将所有的观察者都通知到会花费很多时间;
- 如果存在循环调用可能会导致系统奔溃;
- 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅知道观察目标发生了变化;
3.3 观察者模式的适用环境
- 一个抽象模型有两个方面,其中一个方面依赖与另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用;
- 一个对象的改变将导致一个或多个其他对象也跟着改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁;
- 需要在系统中创建一个触发链。
【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。
【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git
扫描二维码关注公众号,回复:
14784711 查看本文章