观察者模式是使用频率较高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。
定义:
观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象发生改变时其相关依赖对象借得到通知而被自动更新。
观察者模式的别名有发布-订阅(Publish-Subscribe)模式、模型-试图(Model-view——模式、源-监听器(Source-Listener)模式、从属者(Dependents)模式。
观察者模式包含以下4个角色:
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"));
}
}
【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。
【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git