一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情。
观察者模式的概念
观察者模式可以理解为一种基于事件和响应的设计模式。
举例来说某个场景,一个发出通知的角色和一个被通知的角色,对于获取通知这件事,有两种实现方式:
- 第一种是被动通知的方式:被通知者每隔一段时间询问通知者是否有新消息。
- 第二种方式是通知者主动通知:通知者是消息的来源,将被通知者注册到通知者中,当通知者有新消息之后就直接主动通知“被通知者”。
相当于,第一种方式是拉取,第二种方式是推送。
因为现如今开发使用的语言大多数都是“面向对象”的,所以在面向对象开发过程中,我们要尽量面向抽象,而不是面向具体的对象。这样可以尽量避免代码耦合,对于日后的迭代或者升级都比较有好处。
针对上述的第一种“拉取”的实现方式,我们可以明显地看出,这种做法是十分消耗资源的。有时候没有新消息也会持续地对通知者进行访问。对于第二种开发模式,我们就可以将其抽象为一种新的设计模式:观察者模式。
观察者模式类图
我们依旧延续之前的讲解方式,先给出设计模式的类图,然后结合具体场景,给出示例代码,以便更直观地进行学习。
类图:
在观察者模式中,我们称呼上述概念“通知者”为被观察者;称呼“被通知者”为观察者。
对应到类图中,Observer 就是观察者,Subject 就是被观察者。所有观察者都实现了Observer,所有被观察者都实现了Subject。
Subject 的成员变量是ObserverList,存储着已注册的观察者。当有新消息的时候,被观察者会将消息通知到列表中的所有观察者。在这里我们可以看到,被观察者的成员变量ObserverList 依赖的是Observer 接口,而不是具体的观察者,这样就可以做到观察者与被观察者的紧耦合。
代码示例
接下来我们使用具体的代码示例来说明观察者模式的使用。
我们模拟一个场景,全市有很多家4s 店,4s 店正常给消费者提供服务之前需要消费者提前预约,消费者在预约之后需要进行排队,排到之后,4s 店会通知消费者到店服务。
在上述场景中,4s 店就是“被观察者”,而消费者就是“观察者”。
我们来实现这个场景:
首先是观察者接口定义
public interface Observer {
// 每个具体观察者收到消息后被触发的回调方法,
// 具体观察者实现这个方法,做出不同的反应
public void update();
}
具体的观察者
public class ConsumerXiaoHong implements Observer{
@Override
public void update() {
System.out.println("小红收到通知");
}
}
public class ConsumerXiaoMing implements Observer{
@Override
public void update() {
System.out.println("小明收到通知");
}
}
被观察者抽象类定义
public abstract class Subject {
private List<Observer> observerList = new ArrayList<>();
// 添加观察者到观察者列表中
public void attachObserver(Observer observer) {
observerList.add(observer);
}
// 从观察者列表中移除观察者
public void detachObserver(Observer observer) {
observerList.remove(observer);
}
// 通知观察者
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update();
}
}
}
具体被观察者
public class Chevrolet extends Subject{
public void newMessage() {
notifyObservers();
}
}
调用
public static void main(String[] args) {
Chevrolet chevrolet4S = new Chevrolet();
ConsumerXiaoHong xiaoHong = new ConsumerXiaoHong();
ConsumerXiaoMing xiaoMing = new ConsumerXiaoMing();
chevrolet4S.attachObserver(xiaoHong);
chevrolet4S.attachObserver(xiaoMing);
chevrolet4S.newMessage();
}
输出结果
小红收到通知
小明收到通知
总结
观察者模式的讲解结合类图和代码示例应该很好理解。
在日常开发中这个模式也是比较经常使用到的一种设计模式,但是上述场景比较简单,我们依旧需要根据不同场景进行定制化,以达到实现业务需求的目的。