C++ 观察者模式实现
观察者模式
主体(被观察者)通知一个或多个观察者状态改变/数据更新/事件发生。
描述

C++ 实现观察者模式有几个要点:
- 观察者都有一个共同的抽象基类 Listener,定义了一个纯虚接口OnNotified(),主体调用该接口通知观察者
- 每个观察者 ConcreteListener继承自抽象基类Listener,并实现OnNotified()方法
- 主体提供了注册 Listener的方法RegisterListener(Listener&),内部通过vector维护 listener 列表;当主体需要通知观察者时,遍历观察者列表,对每个观察者调用其OnNotified()方法。此处用了面向对象中的多态,即vector中保存的是各个 Listener 的指针或引用,主体只依赖 Listener 的抽象接口,无需关心观察者的具体类型。因为vector不能直接保存引用,可以使用指针或者std::reference_wrapper<Listner>
- 主体也可以根据需要,提供 UnregisterListener方法,观察者也可能需要保存主体的指针或引用,用于之后的 Unregister。
示例代码
#include <functional>
#include <vector>
class Listener {
 public:
  virtual ~Listener() = default;
  virtual void OnNotified() = 0;
  // 如果需要传递数据,可以在 OnNotified 接口中增加参数
  // virtual void OnNotified(const Data&) = 0;
};
class ConcreteListener : public Listener {
 public:
  void OnNotified() override {}
};
class Subject {
 public:
  void RegisterListener(Listener& o) {
    listeners_.push_back(o);
  }
 private:
  void NotifyListeners() {
    for (Listener& o : listeners_) {
      o.OnNotified();
    }
  }
  // 注意:vector 不能停直接保存引用,可以用 reference_wrapper
  std::vector<std::reference_wrapper<Listener>> listeners_;
};
传递数据的两种机制:Push 和 Pull
注意:在这个例子中,主体只是通知观察者,如果需要传递信息,有两种做法:
- Push 推:直接在 OnNotified()函数中增加参数,如OnNotified(const Data&)。但是不同的观察者可能需要 Data 中的不同数据
- Pull 拉:OnNotified()不带参数,只负责通知变化,主体提供一组额外的 Getter 方法,当观察者收到通知时,根据自身需要,调用不同的 Getter 方法获取特定数据。
这两种方法都可以,实际项目中 Push 的方式更常见。
观察者模式的好处
观察者模式是 SOLID 原则中,遵循 “OCP 开放关闭原则” 的典型例子:
- 对扩展开放:新的观察者只需要实现 Listener的OnNotified()接口,并向主体注册即可
- 对修改关闭:现有代码(主体的代码、其他观察者的代码)不需要修改
观察者和主体是解耦的:
- 主体不了解观察者的细节,只知道观察者实现了 OnNotified()接口
- 观察者对主体也所知甚少,只知道主体提供了 RegisterListener(Listener& l)方法,并通过Listener的OnNotified()方法通知观察者。
本文作者:Zijian/TENG(微信公众号:好记性如烂笔头),转载请注明原文链接:https://www.cnblogs.com/tengzijian/p/17840711.html
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号