在软件开发中,经常会遇到一个对象状态的变化需要通知其他相关对象的情况。例如,当一个对象改变了自身的状态时,它可能需要通知到其他对象做出相应的变化。在这种情况下,如果对象之间的关系耦合性过高,就会导致代码难以维护和扩展。
观察者模式解决了这一问题。观察者模式(Observer Pattern)是一种常见的行为型设计模式,用于构建对象之间的一对多依赖关系,使得多个观察者对象同时监听一个主题对象。当主题对象状态发生变化时,所有依赖于它的观察者都会收到通知并作出相应的更新。
观察者模式主要包含以下几个角色:
- 主题(Subject): 定义了被观察的对象,包含观察者列表和用于添加、删除观察者的方法。当主题状态发生变化时,会通过调用 notifyObservers 函数通知所有观察者。
- 观察者(Observer): 定义了接收主题通知的接口,包含更新状态的方法,用于在接收到主题通知时执行相应的操作。
- 具体主题(Concrete Subject): 实现了主题接口,负责维护一组观察者并发送通知。当其状态发生变化时,会通知所有注册的观察者。
- 具体观察者(Concrete Observer): 实现了观察者接口,在收到主题的通知后进行相应的更新操作。
通过观察 Subject 的 UML 图,我们看到里面有一个 observers 的成员变量,用来记录所有的订阅这个主题的观察者。既然 Subject 是通过 notifyObservers 函数通知所有观察者的,那这个函数内部应当有一个观察者的迭代器,通过这个迭代器通知到每一个观察者。下面是 notifyObservers 函数实现的一个例子:
public abstract class Subject {
private ArrayList<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
pubilc void notifyObservers() {
Iterator it = observers.oterator();
while (it.hasNext()) {
Observer observer = (Observer)it.next();
observer.update(this);
}
}
}
现在我们知道了状态变化的时候调用的是 notifyObservers 函数,那它是在哪里被调用的呢?这个问题的答案就在 Concrete Subject,这个具体的主题可以有各种各样的类型,以常见的生产者-消费者模型为例,假如 Observer 是消费者,它们订阅了物品的数量,当物品的数量大于 0 的时候就去通知消费者。下面是一个简单的 GoodSubject 例子:
public class GoodSubject {
private int num;
public void IncGoodNumber() {
num++;
if (num > 0) {
notifyObservers();
}
}
}
观察者模式的核心思想在于建立一个发布者(Subject)和订阅者(Observer)之间的订阅关系。当发布者状态改变时,所有订阅者都会收到通知,并进行相应的处理。
- 注册与通知机制: 观察者将自己注册到主题对象中,在主题状态发生变化时,通知所有注册的观察者。
- 解耦与灵活性: 观察者模式实现了发布者和订阅者之间的解耦,使得发布者和订阅者之间不直接相互调用,提高了代码的灵活性和可维护性。
观察者模式在实际开发中有着广泛的应用,特别适用于以下场景:
- 事件处理系统: 在GUI开发、游戏开发等领域,观察者模式常被用于事件处理系统,当某个事件发生时通知相关观察者做出相应响应。
- 消息通知系统: 消息推送、订阅服务等场景中,可以使用观察者模式实现消息的发布和订阅,实现异步通知机制。
- 数据更新与展示: 在MVC(Model-View-Controller)模式中,模型层的数据更新时常使用观察者模式通知视图层进行更新展示。
Last modified on 2023-12-31