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. 总结
运行截图