C++监听者模式:原理、建立与应用案例

监听者模式(Observer Pattern)是软件设计模式中最常用的行为型模式之一,它定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。本文将深入探讨C++中监听者模式的实现方式、优缺点以及实际应用案例。

1. 监听者模式概述

监听者模式包含两个主要角色:

  • Subject(主题) :被观察的对象,它维护一组观察者,提供添加和删除观察者的接口
  • Observer(观察者) :定义了一个更新接口,当主题状态改变时被调用
Subject
+attach(Observer* observer)
+detach(Observer* observer)
+notify()
«interface»
Observer
+update()
ConcreteSubject
-state
+getState()
+setState()
ConcreteObserver
-subject
+update()

2. C++实现监听者模式

2.1 基础实现

#include <iostream>
  #include <vector>
    #include <algorithm>
      // 前向声明
      class Observer;
      // 主题接口
      class Subject {
      public:
      virtual ~Subject() = default;
      virtual void attach(Observer* observer) = 0;
      virtual void detach(Observer* observer) = 0;
      virtual void notify() = 0;
      };
      // 观察者接口
      class Observer {
      public:
      virtual ~Observer() = default;
      virtual void update() = 0;
      };
      // 具体主题
      class ConcreteSubject : public Subject {
      public:
      void attach(Observer* observer) override {
      observers_.push_back(observer);
      }
      void detach(Observer* observer) override {
      observers_.erase(std::remove(observers_.begin(), observers_.end(), observer), observers_.end());
      }
      void notify() override {
      for (auto observer : observers_) {
      observer->update();
      }
      }
      void setState(int state) {
      state_ = state;
      notify();
      }
      int getState() const { return state_; }
      private:
      int state_ = 0;
      std::vector<Observer*> observers_;
        };
        // 具体观察者
        class ConcreteObserver : public Observer {
        public:
        ConcreteObserver(ConcreteSubject* subject) : subject_(subject) {
        subject_->attach(this);
        }
        ~ConcreteObserver() {
        if (subject_) {
        subject_->detach(this);
        }
        }
        void update() override {
        std::cout << "Observer received update. New state: " << subject_->getState() << std::endl;
          }
          private:
          ConcreteSubject* subject_;
          };

2.2 使用示例

int main() {
ConcreteSubject subject;
ConcreteObserver observer1(&subject);
ConcreteObserver observer2(&subject);
subject.setState(10);
subject.setState(20);
return 0;
}

3. 现代C++改进实现

C++11及以后版本提供了更现代化的实现方式:

#include <iostream>
  #include <vector>
    #include <memory>
      #include <functional>
        class Subject {
        public:
        using Observer = std::function<void(int)>;
          void attach(Observer observer) {
          observers_.push_back(observer);
          }
          void notify(int state) {
          for (auto& observer : observers_) {
          observer(state);
          }
          }
          private:
          std::vector<Observer> observers_;
            };
            int main() {
            Subject subject;
            // 使用lambda表达式作为观察者
            auto observer1 = [](int state) {
            std::cout << "Observer1: State changed to " << state << std::endl;
            };
            auto observer2 = [](int state) {
            std::cout << "Observer2: State changed to " << state << std::endl;
            };
            subject.attach(observer1);
            subject.attach(observer2);
            subject.notify(10);
            subject.notify(20);
            return 0;
            }

4. 应用案例

4.1 GUI事件处理

监听者模式在GUI框架中广泛应用。例如,按钮点击事件的处理:

class Button {
public:
using ClickHandler = std::function<void()>;
  void addClickListener(ClickHandler handler) {
  clickHandlers_.push_back(handler);
  }
  void click() {
  for (auto& handler : clickHandlers_) {
  handler();
  }
  }
  private:
  std::vector<ClickHandler> clickHandlers_;
    };
    int main() {
    Button button;
    button.addClickListener([]() {
    std::cout << "Button clicked! Handler 1" << std::endl;
    });
    button.addClickListener([]() {
    std::cout << "Button clicked! Handler 2" << std::endl;
    });
    button.click();
    return 0;
    }

4.2 游戏开发中的事件系统

在游戏开发中,监听者模式常用于处理游戏事件:

#include <string>
  #include <unordered_map>
    #include <vector>
      class GameEvent {
      public:
      enum class Type { PLAYER_HIT, ENEMY_DIED, LEVEL_COMPLETED };
      GameEvent(Type type, const std::string& data) : type_(type), data_(data) {}
      Type getType() const { return type_; }
      const std::string& getData() const { return data_; }
      private:
      Type type_;
      std::string data_;
      };
      class EventDispatcher {
      public:
      using EventHandler = std::function<void(const GameEvent&)>;
      void addListener(GameEvent::Type type, EventHandler handler) {
      listeners_[type].push_back(handler);
      }
      void dispatch(const GameEvent& event) {
      auto it = listeners_.find(event.getType());
      if (it != listeners_.end()) {
      for (auto& handler : it->second) {
      handler(event);
      }
      }
      }
      private:
      std::unordered_map<GameEvent::Type, std::vector<EventHandler>> listeners_;
        };

5. 监听者模式的优缺点

优点缺点
松耦合:主题和观察者之间松耦合通知顺序不可控
支持广播通信可能导致性能问题(大量观察者时)
符合开闭原则:可以新增观察者而不修改主题可能导致循环引用
动态建立对象间的关系观察者不知道彼此的存在

6. 与其他模式的关系

监听者模式
发布-订阅模式
中介者模式
责任链模式
  • 发布-订阅模式:监听者模式的变体,通常通过消息队列实现
  • 中介者模式:通过中介者对象来封装一系列对象的交互
  • 责任链模式:请求沿着处理链传递,直到有对象处理它

7. 性能考虑

当观察者数量较多时,可以考虑以下优化策略:

  1. 批量通知:积累多个变化后一次性通知
  2. 异步通知:使用线程池或消息队列异步处理通知
  3. 观察者优先级:为观察者设置优先级,控制通知顺序
  4. 惰性更新:标记观察者为"脏",在需要时才更新

8. 总结

监听者模式是C++中实现事件驱动系统的强大工具,它提供了一种松耦合的方式来实现对象间的通信。现代C++的特性(如lambda表达式、std::function)使得监听者模式的实现更加简洁和灵活。在实际应用中,需要根据具体场景权衡其优缺点,并考虑性能优化策略。

通过合理使用监听者模式,可以构建出更加模块化、可维护和可扩展的软件系统。

posted @ 2026-01-23 14:04  clnchanpin  阅读(3)  评论(0)    收藏  举报