如何在Observer中处理具有不同状态值类型的Observable

Bas*_*scy 7 c++ design-patterns arduino observable

(首先是上下文和问题,帖子底部的骨架代码)

我们正在创建和实现一个C++框架,以便在Arduino等环境中使用.

为此,我想使用Observer模式,其中任何对传感器(Observables)的状态更改感兴趣的组件都可以自己注册,并且Observable会通过调用notification()Observer 的方法将其自身作为参数来通知这些更改.

一个观察者可以观察到多个Observable,反之亦然.

问题在于Observer需要提取Observable的当前状态并对其执行某些操作,并且此当前状态可以采用所有形式和大小,具体取决于Observable的特定传感器.

它当然可以是序数值,它们是有限的并且可以被编码出来,就像我在下面的代码中使用该方法所做的那样,getValueasInt()但它也可以是传感器特定的结构,即对于RealTimeClock,它提供日期和时间的结构值.结构当然在编译时定义,并针对特定传感器进行修复.

我的问题:什么是最优雅,未来修改的解决方案或模式?

编辑:请注意,由于Arduino限制,因此无法进行dynamic_cast <>构造


我创建了以下类层次结构(框架代码):

class SenseNode
{
public:
  SenseNode() {};
  SenseNode(uint8_t aNodeId): id(aNodeId) {}
  virtual ~SenseNode() {}

  uint8_t getId() { return id; };
private:
  uint8_t id = 0;
};

class SenseStateNode : virtual public SenseNode
{
public:
  SenseStateNode(uint8_t aNodeId) : SenseNode(aNodeId) {}
  virtual ~SenseStateNode() {}

  /** Return current node state interpreted as an integer. */
  virtual int getValueAsInt();
};

class SenseObservable: public SenseStateNode
{
public:
  SenseObservable(uint8_t aNodeId);
  virtual ~SenseObservable();
  /** Notify all interested observers of the change in state by calling Observer.notification(this) */
  virtual void notifyObservers();
protected:
  virtual void registerObserver(SenseObserver *);
  virtual void unregisterObserver(SenseObserver *);
};

class SenseObserver: virtual public SenseNode
{
public:
  SenseObserver() {};
  virtual ~SenseObserver();

  /** Called by an Observable that we are observing to inform us of a change in state */
  virtual void notification(SenseObservable *observable) {
    int v = observable->getValueAsInt(); // works like a charm
    DateTime d = observable-> ????  // How should i solve this elegantly?
  };
};
Run Code Online (Sandbox Code Playgroud)

Pio*_*ycz 2

如果传感器类型的数量或多或少稳定(而且确实如此 - 在大多数情况下变化非常罕见) - 那么只需在观察者端做好准备以获得几种类型的通知:

class Observer 
{
public:
     virtual void notify(SenseNode& node) {
        // implement here general actions - like printing: not interested in this

     } 
     virtual void notify(RealTimeClock& node) {
          notify(static_cast<SenseNode&>(node)); 
         // by default go to more general function
     } 
     // and follow this pattern - for all nodes you want to handle
     // add corresponding notify(T&) function
};
Run Code Online (Sandbox Code Playgroud)

当发生这种情况时,您必须添加新的节点类型 - 然后只需将新的虚拟函数添加到您的观察者基类中。

要在 Observable 端实现此机制 - 使用双重调度模式

class SenseNode {
public:
    virtual void notifyObserver(Observer& observer) {
       observer.notify(*this);
    }
};

class RealTimeClock : public virtual SenseNode {
public:
    virtual void notifyObserver(Observer& observer) {
       observer.notify(*this); 
        // this will select proper Observer::notify(RealTimeClock&)
        // because *this is RealTimeCLock
    }
};


class SenseObservable: public SenseStateNode
{
public:
  virtual void notifyObservers() {
      for (auto& observer : observers) 
         notifyObserver(observer); 
  }
};
Run Code Online (Sandbox Code Playgroud)

它在实践中如何运作,请参阅现场演示