观察者模式的核心概念
1. 主题(Subject)
主题也被称作被观察对象,它是整个模式的核心枢纽。主题维护着一系列观察者对象的引用,并且提供了注册、移除观察者以及通知观察者状态变化的方法。主题就像一个消息发布中心,掌握着通知哪些对象以及如何通知的关键逻辑。
2. 观察者(Observer)
观察者是那些对主题状态变化感兴趣的对象。它们实现了一个特定的接口(在代码层面),这个接口通常包含一个更新方法,用于在接收到主题的通知时执行相应的操作。每个观察者都"关注"着主题,一旦主题状态改变,观察者就会收到通知并做出反应。
3. 具体主题(ConcreteSubject)
具体主题是主题的具体实现类,它继承或实现主题接口,并实现主题定义的注册、移除和通知等方法。在具体主题类中,会详细定义状态变化的逻辑以及如何触发对观察者的通知。
4. 具体观察者(ConcreteObserver)
具体观察者是观察者接口的具体实现类,它实现了更新方法。在更新方法中,具体观察者会根据主题的状态变化执行具体的业务逻辑。不同的具体观察者可能会根据自身的业务需求,对主题状态变化做出不同的反应。
观察者模式的工作原理
- 注册:观察者对象通过调用主题的注册方法,将自己添加到主题的观察者列表中。此时,主题就知晓了哪些观察者对它的状态变化感兴趣。
- 发布消息:当主题发布消息,它会调用通知方法。这个方法会遍历观察者列表,向每个注册的观察者发送通知。
- 通知与更新:观察者接收到主题的通知后,会调用自身实现的更新方法。
代码示例
下面通过一段Java代码来展示观察者模式的具体实现:
主题代码
java
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(this);
}
}
}
观察者代码
java
// 观察者接口
interface Observer {
void update(Subject subject);
}
// 具体观察者
class ConcreteObserver implements Observer {
private String name;
private int observerState;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(Subject subject) {
observerState = ((ConcreteSubject) subject).getState();
System.out.println(name + " 观察到主题状态变化为: " + observerState);
}
}
观察者模式的优点
1. 解耦对象之间的依赖关系
观察者模式通过将主题和观察者分离,使得它们之间的耦合度降低。主题不需要知道具体的观察者是谁以及它们如何处理状态变化,只需要负责通知。同样,观察者也不需要直接依赖主题的具体实现细节,只需要关注主题的状态变化通知。这种解耦使得系统的可维护性和可扩展性大大提高。
2. 提高系统的灵活性和可维护性
当需要添加新的观察者或者修改主题的行为时,不会对其他部分的代码造成较大的影响。例如,在一个电商系统中,如果要新增一种促销活动通知方式(新的观察者),只需要实现相应的观察者类并注册到促销活动主题中即可,无需修改主题和其他观察者的代码。
3. 支持广播通信
主题可以同时通知多个观察者,实现一对多的通信。这在很多场景下非常有用,比如系统状态的更新需要通知多个不同的模块,通过观察者模式可以轻松实现这种广播式的通知。
观察者模式的缺点
1. 通知顺序不确定性
在主题通知观察者时,无法保证观察者的处理顺序。这可能会导致一些问题,特别是当观察者之间存在依赖关系时。例如,观察者A的处理结果可能会影响观察者B的处理逻辑,但由于通知顺序的不确定性,可能会先通知B再通知A,从而导致错误的结果。
2. 可能导致性能问题
如果观察者数量过多,主题在通知所有观察者时可能会消耗较多的时间和资源,影响系统的性能。尤其是在每次状态变化都需要通知大量观察者的情况下,这种性能问题可能会更加明显。
3. 循环依赖风险
如果观察者在更新过程中又反过来修改主题的状态,可能会导致循环调用,使系统陷入死循环。因此,在设计和实现观察者模式时,需要特别注意避免这种循环依赖的情况。