讲解:侯捷面向对象高级编程——观察者模式(Observer Pattern)
Observer(观察者)模式是一种行为型设计模式,定义了对象之间的一对多依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这种模式广泛用于实现事件处理系统、数据驱动更新以及 MVC 模式中的视图更新。
主要结构:
-
Subject(被观察者/主题):
- 负责维护观察者列表。
- 提供方法用于注册、移除观察者。
- 当自身状态发生改变时,通知所有观察者。
-
Observer(观察者):
- 定义了一个接口,包含
update()
方法,观察者通过实现该方法来接收通知。 - 当被观察者的状态变化时,被通知更新。
- 定义了一个接口,包含
-
ConcreteSubject(具体主题):
- 实现具体的状态变化逻辑。
- 继承自
Subject
并扩展具体的功能。
- ConcreteObserver(具体观察者):
- 继承自
Observer
,实现更新逻辑。 - 它们会根据
Subject
的通知来更新自己。
UML 图:
补充:符号的意义
-
通过
o--
语法,表示委托(composition 或 association) 关系 -
继承关系用
<|--
来绘制 -
+
(Public / 公有):- 表示该属性或方法是公有的,即可以被所有对象访问。无论是同一个类、子类,还是类外部的对象,都可以访问公有成员。
-
-
(Private / 私有):- 表示该属性或方法是私有的,只能在类的内部访问,外部类或子类都无法直接访问。
-
#
(Protected / 受保护):- 表示该属性或方法是受保护的,只能在类内部或其子类中访问,外部类无法访问。
-
~
(Package / 默认访问):- 表示包级别的访问控制(在 C++ 中相当于“友元”或 Java 的 package-private)。只有在相同包中的类可以访问该成员,包外的类无法访问。
观察者模式的实现步骤:
- 定义 Subject 类:负责维护观察者的注册和通知方法。
- 定义 Observer 接口:声明
update()
方法,所有观察者类必须实现这个接口。 - 定义 ConcreteSubject 和 ConcreteObserver:
ConcreteSubject
持有状态,当状态改变时调用notify()
通知观察者。ConcreteObserver
实现update()
方法以接收被观察者的通知。
使用场景:
- GUI 系统:当用户进行操作时,需要更新多个视图,比如按钮点击更新多个面板。
- 事件驱动系统:事件发生时,多个处理模块需要对事件进行响应。
- 模型-视图-控制器 (MVC):视图(观察者)需要监听模型(被观察者)的变化。
代码示例:
#include <iostream>
#include <vector>
using namespace std;
// 前向声明
class Subject;
// 观察者接口类
class Observer {
public:
virtual void update(Subject* sub, int value) = 0; // 纯虚函数,强制继承类实现该方法
};
// 被观察者类
class Subject {
int m_value; // 被观察者状态
vector<Observer*> m_views; // 观察者列表
public:
// 注册观察者
void attach(Observer* obs) {
m_views.push_back(obs);
}
// 修改状态并通知观察者
void set_val(int value) {
m_value = value;
notify();
}
// 通知所有观察者状态变化
void notify() {
for (int i = 0; i < m_views.size(); ++i) {
m_views[i]->update(this, m_value); // 调用每个观察者的 update 方法
}
}
int get_val() const {
return m_value;
}
};
// 具体的观察者实现类
class ConcreteObserver : public Observer {
string m_name; // 观察者名称,用于标识
public:
ConcreteObserver(const string& name) : m_name(name) {}
// 实现 update 方法
void update(Subject* sub, int value) override {
cout << "Observer " << m_name << " has been notified. New value: " << value << endl;
}
};
int main() {
Subject subject; // 创建被观察者对象
// 创建观察者对象
ConcreteObserver observer1("Observer1");
ConcreteObserver observer2("Observer2");
// 注册观察者
subject.attach(&observer1);
subject.attach(&observer2);
// 改变被观察者状态并通知观察者
subject.set_val(10);
subject.set_val(20);
return 0;
}
在这个例子中,Subject
持有观察者的列表,当状态 m_value
变化时,所有观察者都会通过 update
方法得到通知。
输出结果
Observer Observer1 has been notified. New value: 10
Observer Observer2 has been notified. New value: 10
Observer Observer1 has been notified. New value: 20
Observer Observer2 has been notified. New value: 20
总结适用场景:
- 事件驱动系统:比如 GUI 系统中,按钮点击事件通知多个监听器。
- 数据变化的多视图更新:如 MVC 模式中,模型变化时,通知视图更新。
- 分布式系统中的状态同步:多个模块依赖某一模块的状态变化。
Observer 模式非常适合那些需要状态变化通知机制的场景,它提供了一种优雅的方式来管理对象之间的依赖关系。