观察者模式是一种订阅机制:观察者对象可以第一时间收到其观察对象变化的通知

  • 一个包含所有订阅者对象的表
  • 几个用于订阅和取消订阅的方法

必要时,被订阅者将遍历订阅表,并调用每个观察者的特定方法以通知对应的观察者。

总结起来,观察者模式有一个EventManager,通过它维护订阅关系。消息发布者调用其notify方法,来通知所有订阅者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <vector>
#include <string>
#include <map>

class EventManager {
private:
std::map<std::string, std::vector<EventListener*>> listeners;
public:
void subscribe(std::string eventType, EventListener* l) {
listeners[eventType].push_back(l);
}
void unsubscribe(std::string eventType, EventListener* l) {
for (std::vector<EventListener*>::iterator it = listeners[eventType].begin(); it != listeners[eventType].end(); it++) {
if (*it == l) {
listeners[eventType].erase(it);
return;
}
}
}
void notify(std::string eventType, std::string data) {
for (EventListener* l : listeners[eventType]) {
l->update(data);
}
}
};

class Editor {
private:
File* file;
public:
EventManager* events;
Editor() {
events = new EventManager();
}
~Editor() {
if (events) delete events;
}
void openFile(std::string path) {
file = new File(path);
events->notify("open", file->name);
}
void saveFile() {
file->write();
events->notify("save", file->name);
}
};

class EventListener {
public:
virtual ~EventListener() {}
virtual void update(std::string filename) = 0;
};

class LoggingListener: public EventListener {
private:
File* log;
std::string msg;
public:
LoggingListener(std::string logFilename, std::string message) {
log = new File(logFilename);
msg = message;
}
~LoggingListener() {
if (log) delete log;
}
void update(std::string filename) override {
log->write(filename, msg)
}
};

class EmailAlertsListener: public EventListener {
private:
std::string email;
std::string msg;
public:
EmailAlertsListener(std::string em, std::string message): email(em), msg(message) {}
void update(std::string filename) override {
system.email(email, filename, msg);
}
};

int main(int argc, char* argv[]) {
auto editor = new Editor();
auto logger = new LoggingListener("./log.txt", "file opened");
editor->events->subscribe("open", logger);
auto emailAlerts = new EmailAlertsListener("xx@xx.com", "file changed");
editor->events->subscribe("save", emailAlerts);
// ...
return 0;
}