观察者模式是一种订阅机制:观察者对象可以第一时间收到其观察对象变化的通知
- 一个包含所有订阅者对象的表
- 几个用于订阅和取消订阅的方法
必要时,被订阅者将遍历订阅表,并调用每个观察者的特定方法以通知对应的观察者。
总结起来,观察者模式有一个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; }
|