观察者模式
2025-07-01
1. 问题背景
现在有三个类:机器类,工人类,订单类
机器类有一个属性叫 isBroken,类型为boolean,其值为false时,代表机器正常,工人和订单都不受影响
但是当其值为true时,工人需要去进行维修,同时订单状态也会设置为异常
也就是说,当机器类的状态变为异常的一瞬间,立马通知订单、工人进行相应的响应,比如说订单状态应该变为异常,工人状态应该变为维修中等等
2. 解决方案
2.1 轮询
在不了解观察者设计模式的时候你可能会想到通过轮询的方式进行,也就是说订单和工人,每10s去查询一次机器的状态,如果机器状态改变,那么就进行相应的业务逻辑
这样一定程度上可以解决问题,但是有几个明显的缺陷
每10s一次,性能肯定要受到影响
消息也不及时,根本没办法保证消息及时更新
2.2 硬通知
机器状态的改变,一定有一个函数去修改它的状态,那么我只需要在修改它 is Broken为true的时候,同时进行工人的业务逻辑以及订单的业务逻辑不就好了吗?
这样其实完全可以解决问题,但是也有几个缺陷
如果你要通知的对象只有工人和订单两个这倒是没问题,两行代码分别调用订单的业务逻辑函数和工人的业务逻辑函数即可,那如果有一万个你要通知的对象怎么办
耦合性太高,工人的业务逻辑以及订单的业务逻辑,出现在了机器里面,不方便维护,也不可读,甚至不方便修改、维护、扩展
2.3 观察者模式
观察者模式是一种通过发布-订阅的方式,解耦了被观察者(机器类)与观察者(工人类和订单类)之间的关系,使得一个对象(机器类的is Broken)状态变化时,可以自动通知所有需要关注这个变化的类(工人类和订单类)进行相应的更新或处理。
观察者模式的关键在于将通知机制从具体的业务逻辑中分离出来,这样当机器的 isBroken 状态变化时,机器类本身不需要知道如何处理工人和订单的逻辑,只需要通知工人类和订单类机器状态改变了,然后他们自己执行自己的业务逻辑。
3. 手搓代码环节
3.1 代码结构
3.2 Subject
主题是Machine类的原型,任何一个需要通知其他类进行变化的都需要以上三个方法,所以提出来成为接口,分别是添加观察者,移除观察者,通知所有观察者
package subject; import observer.Observer; public interface Subject { void addObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); }
3.3 Machine
Machine继承上面的主题,并且实现了三个接口,并且有自己的属性isBroken,并提供了get、set方法
package subject; import observer.Observer; import java.util.ArrayList; import java.util.List; public class Machine implements Subject { private final List<Observer> observers = new ArrayList<>(); private boolean isBroken = false; @Override public void addObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.receiveNotification(); } } public void setBroken(Boolean isBroken) { this.isBroken = isBroken; if (isBroken) { notifyObservers(); } } public boolean getIsBroken() { return isBroken; } }
3.3 Observe
每个观察者接受到消息发生变化以后,都需要处理自己的业务逻辑,所以提出来成为方法
package observer; public interface Observer { void receiveNotification(); }
3.4 Worker
package observer; import subject.Machine; public class Worker implements Observer { private Machine machine; public Worker(Machine machine) { this.machine = machine; machine.addObserver(this); } @Override public void receiveNotification() { System.out.println("工人要去维修机器咯"); } }
3.5 Order
package observer; import subject.Machine; public class Order implements Observer { private Machine machine; public Order(Machine machine) { this.machine = machine; machine.addObserver(this); } @Override public void receiveNotification() { System.out.println("订单状态异常咯"); } }
3.6 Main
package app; import observer.Order; import observer.Worker; import subject.Machine; public class Main { public static void main(String[] args) { // 创建机器、工人和订单对象 Machine machine = new Machine(); Worker worker = new Worker(machine); Order order = new Order(machine); // 模拟机器正常运行 for (int i = 1; i <= 10; i++) { System.out.println(machine.getIsBroken()); } System.out.println("机器损坏"); machine.setBroken(true); // 机器损坏,工人和订单会被通知并作出反应 } }
4. 总结
运行截图
发表评论: