观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在事件驱动系统中非常常见,例如用户界面组件、消息传递系统等。
观察者模式的基本概念
- 主题(Subject):主题是被观察的对象,它维护了一个观察者列表,并提供添加、删除和通知观察者的方法。
- 观察者(Observer):观察者是依赖于主题的对象,当主题的状态发生变化时,观察者会收到通知并更新自己的状态。
观察者模式的实现
1. 定义主题接口
主题接口定义了添加、删除和通知观察者的方法。
#include <iostream>
#include <vector>
#include <algorithm>
// 观察者接口
class Observer {
public:
virtual void update() = 0;
virtual ~Observer() {}
};
// 主题接口
class Subject {
private:
std::vector<Observer*> observers;
public:
void attach(Observer* observer) {
observers.push_back(observer);
}
void detach(Observer* observer) {
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}
void notify() {
for (Observer* observer : observers) {
observer->update();
}
}
};
2. 定义具体主题
具体主题是主题接口的具体实现,它维护了一个观察者列表,并在状态发生变化时通知所有观察者。
class ConcreteSubject : public Subject {
private:
int state;
public:
ConcreteSubject(int state) : state(state) {}
void setState(int state) {
this->state = state;
notify(); // 状态变化时通知所有观察者
}
int getState() const {
return state;
}
};
3. 定义具体观察者
具体观察者是观察者接口的具体实现,它在收到通知时更新自己的状态。
class ConcreteObserverA : public Observer {
private:
ConcreteSubject* subject;
public:
ConcreteObserverA(ConcreteSubject* subject) : subject(subject) {}
void update() override {
std::cout << "ConcreteObserverA received update, new state: " << subject->getState() << std::endl;
}
};
class ConcreteObserverB : public Observer {
private:
ConcreteSubject* subject;
public:
ConcreteObserverB(ConcreteSubject* subject) : subject(subject) {}
void update() override {
std::cout << "ConcreteObserverB received update, new state: " << subject->getState() << std::endl;
}
};
4. 客户端代码
客户端代码创建具体主题和具体观察者对象,并将观察者注册到主题中。当主题的状态发生变化时,所有观察者都会收到通知并更新自己的状态。
int main() {
ConcreteSubject subject(0);
ConcreteObserverA observerA(&subject);
ConcreteObserverB observerB(&subject);
subject.attach(&observerA);
subject.attach(&observerB);
// 改变主题的状态
subject.setState(10);
// 移除一个观察者
subject.detach(&observerA);
// 再次改变主题的状态
subject.setState(20);
return 0;
}
详细解释
-
主题接口
Subject:class Subject { private: std::vector<Observer*> observers; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end()); } void notify() { for (Observer* observer : observers) { observer->update(); } } };attach方法用于添加观察者。detach方法用于移除观察者。notify方法用于通知所有观察者。
-
具体主题
ConcreteSubject:class ConcreteSubject : public Subject { private: int state; public: ConcreteSubject(int state) : state(state) {} void setState(int state) { this->state = state; notify(); // 状态变化时通知所有观察者 } int getState() const { return state; } };state是主题的状态。setState方法用于设置主题的状态,并在状态变化时调用notify方法通知所有观察者。getState方法用于获取主题的状态。
-
观察者接口
Observer:class Observer { public: virtual void update() = 0; virtual ~Observer() {} };update方法是观察者接收到通知时需要执行的方法。
-
具体观察者
ConcreteObserverA和ConcreteObserverB:class ConcreteObserverA : public Observer { private: ConcreteSubject* subject; public: ConcreteObserverA(ConcreteSubject* subject) : subject(subject) {} void update() override { std::cout << "ConcreteObserverA received update, new state: " << subject->getState() << std::endl; } }; class ConcreteObserverB : public Observer { private: ConcreteSubject* subject; public: ConcreteObserverB(ConcreteSubject* subject) : subject(subject) {} void update() override { std::cout << "ConcreteObserverB received update, new state: " << subject->getState() << std::endl; } };ConcreteObserverA和ConcreteObserverB是观察者接口的具体实现。update方法在接收到通知时更新自己的状态,并输出当前主题的状态。
-
客户端代码
main:int main() { ConcreteSubject subject(0); ConcreteObserverA observerA(&subject); ConcreteObserverB observerB(&subject); subject.attach(&observerA); subject.attach(&observerB); // 改变主题的状态 subject.setState(10); // 移除一个观察者 subject.detach(&observerA); // 再次改变主题的状态 subject.setState(20); return 0; }- 创建一个具体主题
subject,初始状态为 0。 - 创建两个具体观察者
observerA和observerB,并将它们注册到subject中。 - 改变
subject的状态为 10,所有观察者都会收到通知并更新自己的状态。 - 移除
observerA。 - 再次改变
subject的状态为 20,只有observerB会收到通知并更新自己的状态。
- 创建一个具体主题
&spm=1001.2101.3001.5002&articleId=147042944&d=1&t=3&u=9a2964e2bc664c8b937bdb4418744cd0)
316

被折叠的 条评论
为什么被折叠?



