观察者模式
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;@Overridepublic void addObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic 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. 总结
运行截图