系列文章目录
什么是观察者模式
- 先讲什么是行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象 之间的相互通信和协作,进一步明确对象的职责。
- 观察者模式,是一种行为性模型,又叫发布-订阅模式,他定义对象之间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
观察者模式职责
观察者模式主要用于1对N的通知。当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出相应。
实现有两种方式:
- 推:每次都会把通知以广播的方式发送给所有观察者,所有的观察者只能被动接收。
- 拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定。
应用实例
现实中有一个金额变化以后,会有短信提示和支付宝提示的例子,短信和支付宝就是金额变化的观察者。
传统模式
金额数据类
public class MoneyData {
private BigDecimal amount;
private SMS sms;
MoneyData(BigDecimal value){
amount = value;
sms = new SMS();
}
public void increase(BigDecimal value){
amount = amount.add(value);
sms.sendMsg("通知:余额+"+value+",现余额为:"+amount);
}
public void decrease(BigDecimal value){
amount = amount.subtract(value);
sms.sendMsg("通知:余额-"+value+",现余额为:"+amount);
}
}
短信类
public class SMS {
public void sendMsg(String str){
System.out.println("短信"+str);
}
}
客户端类
public class Client {
public static void main(String[] args) {
MoneyData moneyData = new MoneyData(new BigDecimal("5.20"));
moneyData.increase(new BigDecimal("13.14"));
moneyData.decrease(new BigDecimal("13.14"));
}
}
/**
* 短信通知:余额+13.14,现余额为:18.34
* 短信通知:余额-13.14,现余额为:5.20
*/
传统模式扩展性十分差,如果新增一个支付宝观察者,需要修改金额数据类,增加一个成员变量。违反了ocp原则(开闭原则)。可以通过观察者模式修改,让观察者放入一个List列表中
观察者模式
Subject抽象类
public abstract class Subject {
protected List<Observer> observers = new LinkedList<>();
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
if(observers.contains(o)){
observers.remove(o);
}
}
public abstract void notifyObservers(String changeValue);
}
Subject 的具体实现类
public class MoneyData extends Subject{
private BigDecimal amount;
MoneyData(BigDecimal value){
this.amount = value;
}
public void increase(BigDecimal value){
amount = amount.add(value);
notifyObservers("+"+value);
}
public void decrease(BigDecimal value){
amount = amount.subtract(value);
notifyObservers("-"+value);
}
@Override
public void notifyObservers(String changeValue) {
for (Observer observer : observers) {
observer.sendMsg("通知:余额"+changeValue+",现余额为"+amount);
}
}
}
Observer(观察者)接口
public interface Observer {
public void sendMsg(String msg);
}
Observer(观察者)的两个具体实现类
public class SMS implements Observer{
@Override
public void sendMsg(String msg) {
System.out.println("短信"+msg);
}
}
public class Alipay implements Observer{
@Override
public void sendMsg(String msg) {
System.out.println("支付宝"+msg);
}
}
客户端类
public class Client {
public static void main(String[] args) {
MoneyData moneyData = new MoneyData(new BigDecimal("13.14"));
moneyData.registerObserver(new SMS());
moneyData.increase(new BigDecimal("52.00"));
moneyData.decrease(new BigDecimal("52.00"));
moneyData.registerObserver(new Alipay());
moneyData.increase(new BigDecimal("5.20"));
moneyData.decrease(new BigDecimal("5.20"));
}
}
/**
* 短信通知:余额+52.00,现余额为65.14
* 短信通知:余额-52.00,现余额为13.14
* 短信通知:余额+5.20,现余额为18.34
* 支付宝通知:余额+5.20,现余额为18.34
* 短信通知:余额-5.20,现余额为13.14
* 支付宝通知:余额-5.20,现余额为13.14
*/
应用场景
- 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。