通八洲科技

C++如何实现观察者设计模式?C++代码解耦实战【设计模式】

日期:2025-12-25 00:00 / 作者:尼克
观察者模式在C++中通过抽象基类解耦Subject与Observer,用std::vector+weak_ptr管理观察者并自动清理,模板化SubjectBase提升复用性,具体类仅需继承并调用notify(),新增观察者零侵入。

观察者模式在C++中核心是解耦“被观察者”(Subject)和“观察者”(Observer),让两者只依赖抽象,不依赖具体实现。关键在于用抽象类定义接口、用容器管理观察者、用虚函数触发通知——不用信号槽、不依赖第三方库,纯标准C++就能落地。

定义抽象观察者和被观察者接口

先写两个纯虚基类:Observer 声明 update() 接口,Subject 声明 attach()/detach()/notify() 接口。所有具体类都继承它们,这样新增观察者或被观察者时,原有代码完全不用改。

注意:Observer 的 update() 通常接收 const Subject& 或 shared_ptr,避免拷贝、防止误修改;Subject 内部用 std::vector<:weak_ptr>> 存观察者,避免循环引用导致内存泄漏。

实现可复用的 Subject 基类模板

把通用逻辑抽成模板,减少重复代码。例如:

// 模板化 Subject 基类,自动管理 weak_ptr 观察者
template
class SubjectBase {
protected:
  std::vector<:weak_ptr>> observers_;
public:
  void attach(std::shared_ptr obs) {
    observers_.push_back(obs);
  }
  void notify() const {
    for (auto it = observers_.begin(); it != observers_.end();) {
      if (auto obs = it->lock()) {
        obs->update(*this);
        ++it;
      } else {
        it = observers_.erase(it); // 自动清理已销毁的观察者
      }
    }
  }
};

具体业务类按需继承并触发通知

比如一个温度传感器类:

class TemperatureSensor : public SubjectBase {
private:
  double temperature_ = 0.0;
public:
  void setTemperature(double t) {
    temperature_ = t;
    notify(); // 数据一变就广播,不关心谁在监听
  }
  double getTemperature() const { return temperature_; }
};

再写具体观察者,比如控制台打印器和日志记录器,都只实现自己的 update(),互不影响:

使用时只需组合,不修改已有类

main() 里创建对象、建立关系即可:

int main() {
  auto sensor = std::make_shared();
  auto display = std::make_shared();
  auto logger = std::make_shared();

  sensor->attach(display);
  sensor->attach(logger);

  sensor->setTemperature(25.6); // 自动触发 display 和 logger
  sensor->setTemperature(26.1); // 同样自动通知
}

以后加新功能(比如发邮件告警),只要写个 EmailAlert 类继承 Observer,实现 update(),再 attach 进去——零侵入、无编译依赖、职责清晰。

基本上就这些。不复杂但容易忽略 weak_ptr 清理、const 正确性、以及模板接口的泛化粒度。写熟了,一个项目里几十个松耦合的通知场景,都能靠这几行基类搞定。