如何在 Observer 中处理具有不同状态值类型的 Observable [英] How to handle Observables with different state-value types in the Observer

查看:27
本文介绍了如何在 Observer 中处理具有不同状态值类型的 Observable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(先是上下文和问题,文章底部有框架代码)

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

We are creating and implementing a C++ framework to use in environments like Arduino.

为此,我想使用观察者模式,其中任何对传感器状态变化感兴趣的组件(Observables)都可以注册自己,并且它会通过 Observable 调用 notification() 以自身为参数的 Observer 方法.

For this I want to use the Observer pattern, where any component interested in state-changes of sensors (Observables) can register itself and it will get notified of those changes by the Observable calling the notification() method of the Observer with itself as a parameter.

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

One Observer can observe multiple Observables, and vice versa.

问题在于,Observer 需要提取 Observable 的当前状态并对其进行处理,而当前状态可以采用各种形式和大小,具体取决于作为 Observable 的特定传感器.

The problem lies in the fact that the Observer needs to extract the current state of the Observable and do something with it, and this current state can take all forms and sizes, depending on the particular sensor that is the Observable.

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

It can of course be ordinal values, which are finite and can be coded out, like I did in the code below with the method getValueasInt() but it can also be sensor-specific structures, i.e. for a RealTimeClock, which delivers a struct of date and time values. The struct are of course defined at compile time, and fixed for a specific sensor.

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

请注意,由于 Arduino 的限制,无法进行 dynamic_cast<> 构造

Note that dynamic_cast<> constructions are not possible because of Arduino limitations

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

I have created the following class-hierarchy (skeleton code):

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?
  };
};

<小时>

推荐答案

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

If the number of sensor types is more or less stable (and it is - the changes are pretty rare in most cases) - then just be prepared on Observer side to get several kind of notifications:

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
};

当它发生时,您必须添加新的节点类型 - 然后将新的虚函数添加到您的基本 Observer 类中.

When it happens you have to add new node type - then just add new virtual function to your base Observer class.

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

To implement this mechanism on Observable side - use double dispatch pattern:

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); 
  }
};

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

How it works in practice, see live demo

这篇关于如何在 Observer 中处理具有不同状态值类型的 Observable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆