23种设计模式-观察者(Observer)设计模式
文章目录
- 一.什么是观察者模式?
- 二.观察者模式的结构
- 三.观察者模式的应用场景
- 四.观察者模式的优缺点
- 五.观察者模式的实现(C++示例)
- 六.观察者模式的实现(JAVA示例)
- 七.代码解释
- 八.总结
类图: 观察者设计模式类图
一.什么是观察者模式?
观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的一对多关系。即一个对象(称为“主题”)状态发生改变时,会自动通知依赖它的其他对象(称为“观察者”)。这种模式在很多场景中都非常适用,比如发布-订阅系统、事件监听、界面刷新等。
观察者模式的特点是松耦合:观察者和主题不需要彼此了解细节,只需按照约定进行交互,这种设计提升了代码的可维护性和可扩展性。
二.观察者模式的结构
- Subject(主题):又称被观察者,用于存储和管理观察者,并在自身状态变化时通知观察者。
- Observer(观察者):观察者接口,用于定义更新方法,所有观察者实现该接口。
- ConcreteSubject(具体主题):继承自主题接口,实现状态管理和通知观察者的具体逻辑。
- ConcreteObserver(具体观察者):实现观察者接口,通过获取主题更新,执行相应的行为。
三.观察者模式的应用场景
- 事件监听:用户在UI界面点击按钮时,按钮组件通过通知事件监听器实现某种交互。
- 数据变化通知:在数据变化时,多个视图自动更新显示。例如,股票价格变化时,订阅者自动更新价格显示。
- 发布-订阅系统:发布者更新数据时,通知订阅的所有观察者,实现自动信息推送。
四.观察者模式的优缺点
-
优点:
- 解耦:主题与观察者之间的耦合度较低,可以独立扩展。
- 自动通知:当主题状态发生变化时,无需手动通知每个观察者。
-
缺点:
- 通知耗时:当观察者数量较多或更新频繁时,可能会导致性能问题。
- 顺序依赖:如果通知是同步进行的,通知的顺序会影响整个流程。
五.观察者模式的实现(C++示例)
#include <iostream>
#include <vector>
#include <string>
// 观察者接口
class Observer {
public:
virtual void update(const std::string &message) = 0;
};
// 主题接口
class Subject {
public:
virtual void addObserver(Observer* observer) = 0;
virtual void removeObserver(Observer* observer) = 0;
virtual void notifyObservers() = 0;
};
// 具体主题类
class ConcreteSubject : public Subject {
private:
std::vector<Observer*> observers;
std::string message;
public:
void setMessage(const std::string &newMessage) {
message = newMessage;
notifyObservers(); // 通知所有观察者
}
void addObserver(Observer* observer) override {
observers.push_back(observer);
}
void removeObserver(Observer* observer) override {
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}
void notifyObservers() override {
for (Observer* observer : observers) {
observer->update(message);
}
}
};
// 具体观察者类
class ConcreteObserver : public Observer {
private:
std::string name;
public:
ConcreteObserver(const std::string &observerName) : name(observerName) {}
void update(const std::string &message) override {
std::cout << "Observer " << name << " received message: " << message << std::endl;
}
};
// 测试代码
int main() {
ConcreteSubject subject;
// 创建观察者
ConcreteObserver observer1("Observer1");
ConcreteObserver observer2("Observer2");
// 添加观察者
subject.addObserver(&observer1);
subject.addObserver(&observer2);
// 主题更新并通知观察者
subject.setMessage("New message arrived");
// 移除观察者并更新主题
subject.removeObserver(&observer1);
subject.setMessage("Another message");
return 0;
}
六.观察者模式的实现(JAVA示例)
import java.util.ArrayList;
import java.util.List;
// 抽象观察者类
interface Observer {
void update(int state); // 更新方法
}
// 具体观察者A
class ConcreteObserverA implements Observer {
@Override
public void update(int state) {
System.out.println("ConcreteObserverA: State updated to " + state);
}
}
// 具体观察者B
class ConcreteObserverB implements Observer {
@Override
public void update(int state) {
System.out.println("ConcreteObserverB: State updated to " + state);
}
}
// 抽象主题类
abstract class Subject {
protected List<Observer> observers = new ArrayList<>();
// 添加观察者
public void attach(Observer observer) {
observers.add(observer);
}
// 移除观察者
public void detach(Observer observer) {
observers.remove(observer);
}
// 通知所有观察者
public void notifyObservers(int state) {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 具体主题类
class ConcreteSubject extends Subject {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
System.out.println("ConcreteSubject: State changed to " + state);
notifyObservers(state); // 通知观察者
}
}
// 客户端代码
public class ObserverPatternDemo {
public static void main(String[] args) {
// 创建具体主题
ConcreteSubject subject = new ConcreteSubject();
// 创建观察者并订阅
Observer observerA = new ConcreteObserverA();
Observer observerB = new ConcreteObserverB();
subject.attach(observerA);
subject.attach(observerB);
// 更改状态并通知观察者
subject.setState(10);
subject.setState(20);
// 取消观察者A的订阅
subject.detach(observerA);
// 再次更改状态
subject.setState(30);
}
}
七.代码解释
- Observer 接口:Observer是一个抽象基类,包含update方法,所有观察者都要实现该方法,以响应主题的通知。
- Subject 接口:Subject也是一个抽象基类,提供addObserver、removeObserver和notifyObservers方法,主题通过这些方法管理和通知观察者。
- ConcreteSubject 类:这是主题的具体实现类,包含observers向量用于保存观察者。当主题状态改变时,通过调用notifyObservers通知所有观察者。
- ConcreteObserver 类:这是观察者的具体实现类。每个观察者都有一个name属性,并在update方法中响应通知。
- 测试代码:在main函数中创建了一个主题对象subject,并注册两个观察者对象observer1和observer2。主题更新时,所有观察者都会收到通知。
八.总结
观察者模式是一种非常实用的设计模式,特别是在需要通知多个对象的场景中非常合适。它让主题和观察者之间实现了低耦合,从而增强系统的灵活性和扩展性。通过实现一个通用的观察者接口和主题接口,观察者模式能够很好地应对需求的变化,使得观察者可以随时添加、删除,并根据主题的状态变化而自动更新,从而达到良好的解耦效果。