此为设计模式第三谈!
用总-分-总的结构和生活化的例子给你讲解设计模式!
码农不易,各位学者学到东西请点赞收藏支持支持!
开始部分:
总:当一个对象(被观察者)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。就像你,跟你的影子。
分:
1.老规矩,创建一个控制台应用
2.实现编码,这里使用的是NBA比赛例子来辅助理解,想象你是一名体育赛事记者,而你关注的体育赛事(被观察者)是NBA比赛。每当比赛有重要事件发生(如得分,犯规),你(观察者)都需要进行立刻报道。
-
被观察者(NBA比赛):是信息的来源,当比赛状态(得分、时间等)发生变化时,会通知所有关注它的记者(观察者)。
-
观察者(记者):关注比赛的进展,一旦比赛状态变化,立即更新自己的报道。
2.1 观察者模式的四个主要角色
2.1.1 Subject被观察者:持有观察者列表,提供添加和删除观察者的方法,以及通知所有观察者的方法。
2.1.2 Observer观察者:定义一个更新接口,当观察者被通知时,观察者根据需要更新自己状态。
2.1.3 ConcreteSubject具体被观察者:继承或实现Subject接口,当内部状态改变时,会通知所有观察者。
2.1.4 ConcreteObserver具体观察者:实现Observer接口的更新方法,当被通知时,做出相应的反应。
#include <iostream>
#include <vector>
using namespace std;
// 报道者(观察者)接口
class Reporter {
public:
//纯虚函数作为抽象类接口
virtual void update(const string& message) = 0;
};
// NBA比赛(被观察者)接口
class NBAGame {
public:
void attach(Reporter* reporter);//添加
void detach(Reporter* reporter);//删除
void notify(const string& message);//通知
void scoreChanged();
private:
vector<Reporter*> reporters;//观察者列表
};
// 实现NBA比赛
void NBAGame::attach(Reporter* reporter) {
reporters.push_back(reporter);
}
void NBAGame::detach(Reporter* reporter) {
reporters.erase(remove(reporters.begin(), reporters.end(), reporter), reporters.end());
}
void NBAGame::notify(const string& message) {
for (auto reporter : reporters) {
reporter->update(message);
}
}
//发生变化就要通知
void NBAGame::scoreChanged() {
// 模拟比赛得分变化
cout << "比赛得分发生变化。" << endl;
notify("比赛得分发生变化。");
}
// 具体的报道者
class SportsReporter : public Reporter {
public:
void update(const string& message) override {
cout << "体育记者报道:" << message << endl;
}
};
// 具体的报道者
class NewsReporter : public Reporter {
public:
void update(const string& message) override {
cout << "新闻记者报道:" << message << endl;
}
};
int main() {
NBAGame game;
SportsReporter sportsReporter;
NewsReporter newsReporter;
game.attach(&sportsReporter);
game.attach(&newsReporter);
// 模拟比赛得分变化
game.scoreChanged();
// 体育记者不再关注比赛
game.detach(&sportsReporter);
// 再次模拟比赛得分变化
game.scoreChanged();
return 0;
}
3.此结构图辅助理解观察者模式