C++软件设计模式之观察者模式

打印 上一主题 下一主题

主题 1004|帖子 1004|积分 3012

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
观察者模式的动机意图

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生改变时,全部依赖于它的对象都能够主动收到通知并进行相应的更新。
动机意图:


  • 解耦:观察者模式的动机在于解耦对象之间的关系。具体来说,它让一个对象(被观察者或主题)不必要知道具体有哪些对象(观察者)依赖于它,从而降低了对象之间的耦合度。
  • 主动通知:当被观察者的状态发生变化时,全部观察者都会主动收到通知,并执行相应的操纵。这种机制使得体系更加灵活,易于扩展和维护。
适用场合

观察者模式适用于以下场景:

  • 当一个对象的状态变化必要通知其他对象,而且你不知道这些对象的具体数量和类型时。例如,图形用户界面(GUI)中的按钮点击事件,可以通知多个监听器。
  • 当必要在不修改被观察者代码的情况下,动态添加或删除观察者时。这种情况下,观察者模式可以实现松耦合的设计。
  • 当一个对象的状态变化会影响多个其他对象,而且这些对象必要根据状态变化主动更新时。例如,股票价格的变化会影响多个投资者的计谋。
观察者模式的变体

观察者模式有几种常见的变体,具体取决于通知机制、更新方式以及观察者的管理方式。以下是几种常见的变体:

  • 推模型(Push Model)

    • 特点:被观察者主动将状态变化的信息推送给全部观察者。
    • 优点:观察者不必要知道被观察者的内部结构,只必要处理推送过来的数据。
    • 缺点:被观察者必要知道观察者的接口,可能会导致观察者和被观察者之间的耦合。

  • 拉模型(Pull Model)

    • 特点:被观察者仅通知观察者状态已发生变化,观察者必要主动去拉取被观察者的具体状态。
    • 优点:观察者可以只拉取自己感兴趣的部分状态,淘汰不必要的数据传输。
    • 缺点:观察者必要了解被观察者的内部结构。

  • 事件机制(Event-based Model)

    • 特点:被观察者通过事件通知观察者,观察者可以订阅特定类型的事件。
    • 优点:可以处理更复杂的事件类型,支持多种事件的订阅和处理。
    • 缺点:实现复杂度较高。

  • 观察者队列(Observer Queue)

    • 特点:使用队列来管理观察者,当被观察者状态变化时,将通知放入队列中,观察者从队列中取出通知进行处理。
    • 优点:可以实现异步通知,进步体系的并发性能。
    • 缺点:可能引入额外的复杂性和延迟。

  • 弱引用观察者(Weak Reference Observer)

    • 特点:使用弱引用(Weak Reference)来管理观察者,防止观察者对象未被开释时导致的内存泄漏。
    • 优点:可以避免内存泄漏题目。
    • 缺点:必要额外的机制来管理弱引用。

总结

观察者模式通过解耦对象之间的关系,提供了一种灵活且易于扩展的通知机制。它的变体如推模型、拉模型、事件机制等,使得它在差别的场景中可以有差别的实现方式。基于观察者模式的特点,发布-订阅模式、事件驱动架构、MVC模式等软件架构模式在现代软件开发中得到了广泛的应用。这些架构模式不但进步了体系的灵活性和可维护性,还使得体系在面对变化时能够更加从容应对。
下面是观察者模式的差别变体的C++代码示例,包罗推模型、拉模型、事件机制、观察者队列和弱引用观察者。
1. 推模型(Push Model)

在推模型中,被观察者将状态变化的信息主动推送给全部观察者。
示例代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. // 观察者接口
  5. class Observer {
  6. public:
  7.     virtual void update(const std::string& message) = 0;
  8.     virtual ~Observer() = default;
  9. };
  10. // 具体观察者
  11. class ConcreteObserver : public Observer {
  12. public:
  13.     void update(const std::string& message) override {
  14.         std::cout << "Observer received message: " << message << std::endl;
  15.     }
  16. };
  17. // 被观察者接口
  18. class Subject {
  19. public:
  20.     virtual void attach(Observer* observer) = 0;
  21.     virtual void detach(Observer* observer) = 0;
  22.     virtual void notify(const std::string& message) = 0;
  23.     virtual ~Subject() = default;
  24. };
  25. // 具体被观察者
  26. class ConcreteSubject : public Subject {
  27. private:
  28.     std::vector<Observer*> observers;
  29. public:
  30.     void attach(Observer* observer) override {
  31.         observers.push_back(observer);
  32.     }
  33.     void detach(Observer* observer) override {
  34.         observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
  35.     }
  36.     void notify(const std::string& message) override {
  37.         for (Observer* observer : observers) {
  38.             observer->update(message);
  39.         }
  40.     }
  41.     void changeState(const std::string& message) {
  42.         std::cout << "Subject state changed. Notifying observers..." << std::endl;
  43.         notify(message);
  44.     }
  45. };
  46. int main() {
  47.     ConcreteSubject subject;
  48.     ConcreteObserver observer1;
  49.     ConcreteObserver observer2;
  50.     subject.attach(&observer1);
  51.     subject.attach(&observer2);
  52.     subject.changeState("Hello Observers!");
  53.     subject.detach(&observer1);
  54.     subject.changeState("Hello again!");
  55.     return 0;
  56. }
复制代码

2. 拉模型(Pull Model)

在拉模型中,被观察者仅通知观察者状态已发生变化,观察者必要主动去拉取被观察者的具体状态。
示例代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. // 被观察者接口
  5. class Subject {
  6. public:
  7.     virtual std::string getState() const = 0;
  8.     virtual void notify() = 0;
  9.     virtual void setState(const std::string& state) = 0;
  10.     virtual void attach(class Observer* observer) = 0;
  11.     virtual void detach(class Observer* observer) = 0;
  12.     virtual ~Subject() = default;
  13. };
  14. // 具体被观察者
  15. class ConcreteSubject : public Subject {
  16. private:
  17.     std::string state;
  18.     std::vector<class Observer*> observers;
  19. public:
  20.     std::string getState() const override {
  21.         return state;
  22.     }
  23.     void setState(const std::string& state) override {
  24.         this->state = state;
  25.         notify();
  26.     }
  27.     void attach(Observer* observer) override {
  28.         observers.push_back(observer);
  29.     }
  30.     void detach(Observer* observer) override {
  31.         observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
  32.     }
  33.     void notify() override {
  34.         for (Observer* observer : observers) {
  35.             observer->update();
  36.         }
  37.     }
  38. };
  39. // 观察者接口
  40. class Observer {
  41. protected:
  42.     Subject* subject;
  43. public:
  44.     Observer(Subject* subject) : subject(subject) {}
  45.     virtual void update() = 0;
  46.     virtual ~Observer() = default;
  47. };
  48. // 具体观察者
  49. class ConcreteObserver : public Observer {
  50. public:
  51.     ConcreteObserver(Subject* subject) : Observer(subject) {}
  52.     void update() override {
  53.         std::string state = subject->getState();
  54.         std::cout << "Observer received state: " << state << std::endl;
  55.     }
  56. };
  57. int main() {
  58.     ConcreteSubject subject;
  59.     ConcreteObserver observer1(&subject);
  60.     ConcreteObserver observer2(&subject);
  61.     subject.attach(&observer1);
  62.     subject.attach(&observer2);
  63.     subject.setState("State 1");
  64.     subject.detach(&observer1);
  65.     subject.setState("State 2");
  66.     return 0;
  67. }
复制代码

3. 事件机制(Event-based Model)

在事件机制中,被观察者通过事件通知观察者,观察者可以订阅特定类型的事件。
示例代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <map>
  5. #include <functional>
  6. // 事件类型
  7. enum class EventType {
  8.     StateChanged,
  9.     DataUpdated
  10. };
  11. // 事件
  12. class Event {
  13. public:
  14.     EventType type;
  15.     std::string data;
  16.     Event(EventType type, const std::string& data) : type(type), data(data) {}
  17. };
  18. // 观察者接口
  19. class Observer {
  20. public:
  21.     virtual void handleEvent(const Event& event) = 0;
  22.     virtual ~Observer() = default;
  23. };
  24. // 具体观察者
  25. class ConcreteObserver : public Observer {
  26. public:
  27.     void handleEvent(const Event& event) override {
  28.         std::cout << "Observer received event of type: " << static_cast<int>(event.type)
  29.                   << " with data: " << event.data << std::endl;
  30.     }
  31. };
  32. // 被观察者接口
  33. class Subject {
  34. private:
  35.     std::map<EventType, std::vector<Observer*>> eventObservers;
  36. public:
  37.     void attach(EventType type, Observer* observer) {
  38.         eventObservers[type].push_back(observer);
  39.     }
  40.     void detach(EventType type, Observer* observer) {
  41.         auto& observers = eventObservers[type];
  42.         observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
  43.     }
  44.     void notify(const Event& event) {
  45.         auto& observers = eventObservers[event.type];
  46.         for (Observer* observer : observers) {
  47.             observer->handleEvent(event);
  48.         }
  49.     }
  50.     void changeState(const std::string& state) {
  51.         std::cout << "Subject state changed." << std::endl;
  52.         notify(Event(EventType::StateChanged, state));
  53.     }
  54.     void updateData(const std::string& data) {
  55.         std::cout << "Subject data updated." << std::endl;
  56.         notify(Event(EventType::DataUpdated, data));
  57.     }
  58. };
  59. int main() {
  60.     Subject subject;
  61.     ConcreteObserver observer1;
  62.     ConcreteObserver observer2;
  63.     subject.attach(EventType::StateChanged, &observer1);
  64.     subject.attach(EventType::DataUpdated, &observer2);
  65.     subject.changeState("New State");
  66.     subject.updateData("New Data");
  67.     subject.detach(EventType::StateChanged, &observer1);
  68.     subject.changeState("Another State");
  69.     return 0;
  70. }
复制代码

4. 观察者队列(Observer Queue)

在观察者队列中,使用队列来管理观察者,当被观察者状态变化时,将通知放入队列中,观察者从队列中取出通知进行处理。
示例代码

  1. #include <iostream>
  2. #include <queue>
  3. #include <string>
  4. #include <mutex>
  5. #include <thread>
  6. #include <condition_variable>
  7. // 通知类型
  8. class Notification {
  9. public:
  10.     virtual void process() = 0;
  11.     virtual ~Notification() = default;
  12. };
  13. // 具体通知
  14. class ConcreteNotification : public Notification {
  15. private:
  16.     std::string message;
  17. public:
  18.     ConcreteNotification(const std::string& message) : message(message) {}
  19.     void process() override {
  20.         std::cout << "Processing notification: " << message << std::endl;
  21.     }
  22. };
  23. // 观察者队列
  24. class ObserverQueue {
  25. private:
  26.     std::queue<Notification*> queue;
  27.     std::mutex mutex;
  28.     std::condition_variable cv;
  29. public:
  30.     void enqueue(Notification* notification) {
  31.         std::lock_guard<std::mutex> lock(mutex);
  32.         queue.push(notification);
  33.         cv.notify_one();
  34.     }
  35.     void processQueue() {
  36.         while (true) {
  37.             std::unique_lock<std::mutex> lock(mutex);
  38.             cv.wait(lock, [this] { return !queue.empty(); });
  39.             Notification* notification = queue.front();
  40.             queue.pop();
  41.             lock.unlock();
  42.             notification->process();
  43.             delete notification;
  44.         }
  45.     }
  46. };
  47. int main() {
  48.     ObserverQueue queue;
  49.     std::thread worker([&queue]() { queue.processQueue(); });
  50.     queue.enqueue(new ConcreteNotification("Notification 1"));
  51.     queue.enqueue(new ConcreteNotification("Notification 2"));
  52.     queue.enqueue(new ConcreteNotification("Notification 3"));
  53.     worker.join();
  54.     return 0;
  55. }
复制代码

5. 弱引用观察者(Weak Reference Observer)

在弱引用观察者中,使用弱引用(Weak Reference)来管理观察者,防止观察者对象未被开释时导致的内存泄漏。
示例代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <memory>
  4. #include <string>
  5. #include <functional>
  6. // 观察者接口
  7. class Observer {
  8. public:
  9.     virtual void update(const std::string& message) = 0;
  10.     virtual ~Observer() = default;
  11. };
  12. // 具体观察者
  13. class ConcreteObserver : public Observer {
  14. public:
  15.     void update(const std::string& message) override {
  16.         std::cout << "Observer received message: " << message << std::endl;
  17.     }
  18. };
  19. // 被观察者接口
  20. class Subject {
  21. public:
  22.     virtual void attach(std::weak_ptr<Observer> observer) = 0;
  23.     virtual void notify(const std::string& message) = 0;
  24.     virtual ~Subject() = default;
  25. };
  26. // 具体被观察者
  27. class ConcreteSubject : public Subject {
  28. private:
  29.     std::vector<std::weak_ptr<Observer>> observers;
  30. public:
  31.     void attach(std::weak_ptr<Observer> observer) override {
  32.         observers.push_back(observer);
  33.     }
  34.     void notify(const std::string& message) override {
  35.         observers.erase(std::remove_if(observers.begin(), observers.end(),
  36.                                       [](const std::weak_ptr<Observer>& observer) {
  37.                                           return observer.expired();
  38.                                       }), observers.end());
  39.         for (auto& observer : observers) {
  40.             if (auto sharedObserver = observer.lock()) {
  41.                 sharedObserver->update(message);
  42.             }
  43.         }
  44.     }
  45.     void changeState(const std::string& message) {
  46.         std::cout << "Subject state changed. Notifying observers..." << std::endl;
  47.         notify(message);
  48.     }
  49. };
  50. int main() {
  51.     ConcreteSubject subject;
  52.     auto observer1 = std::make_shared<ConcreteObserver>();
  53.     auto observer2 = std::make_shared<ConcreteObserver>();
  54.     subject.attach(observer1);
  55.     subject.attach(observer2);
  56.     subject.changeState("Hello Observers!");
  57.     observer1.reset(); // 释放 observer1
  58.     subject.changeState("Hello again!");
  59.     return 0;
  60. }
复制代码

总结

以上是观察者模式的几种差别变体的C++代码示例。每种变体都有其适用的场景和优缺点,开发者可以根据具体的需求选择合适的实现方式。观察者模式的焦点思想是解耦对象之间的关系,并通过通知机制实现对象之间的通讯。

基于观察者模式特点的软件架构模式

观察者模式的特性使得它在许多软件架构中都有重要的应用,以下是几种基于观察者模式特点的软件架构模式:

  • 发布-订阅模式(Publish-Subscribe Pattern)

    • 特点:发布-订阅模式是观察者模式的一种扩展,它将消息的发送者(发布者)和接收者(订阅者)完全解耦。发布者不必要知道订阅者的存在,订阅者也不必要知道发布者的存在。
    • 应用:常见的应用场景包罗消息队列体系(如 Kafka、RabbitMQ)、事件驱动体系等。
    • 优点:体系组件之间的耦合度极低,适合构建分布式体系。

  • 事件驱动架构(Event-Driven Architecture)

    • 特点:事件驱动架构是一种基于事件的架构模式,体系中的组件通过事件进行通讯。事件的产生和处理通常基于观察者模式。
    • 应用:常见的应用场景包罗图形用户界面、分布式体系、微服务架构等。
    • 优点:体系组件可以异步处理事件,进步体系的可扩展性和响应性。

  • 模型-视图-控制器(MVC)模式

    • 特点:MVC模式将应用步伐分为三个部分:模型(Model)、视图(View)和控制器(Controller)。模型是观察者模式中的被观察者,视图是观察者。当模型的状态发生变化时,视图会主动更新。
    • 应用:常见的应用场景包罗Web应用步伐、桌面应用步伐等。
    • 优点:模型和视图之间的解耦,使得体系更易于维护和扩展。

  • 观察者-被观察者链(Observer-Observable Chain)

    • 特点:在这种架构中,观察者和被观察者可以形成一个链式结构,每个被观察者可以同时是观察者。
    • 应用:常见的应用场景包罗事件流传链、责任链模式等。
    • 优点:可以实现复杂的事件流传和处理机制。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表