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

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

问题描述

(上下文和问题优先,帖子底部为骨架代码)

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

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

为此,我要使用观察者模式,其中任何对传感器状态更改感兴趣的组件(Observables)都可以注册其自身,并且它会通过Observable调用观察者本身作为参数.

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.

一个观察者可以观察多个可观察对象,反之亦然.

One Observer can observe multiple Observables, and vice versa.

问题在于观察者需要提取观察者的当前状态并对其进行处理,并且该当前状态可以采用各种形式和大小,具体取决于观察者所使用的特定传感器.

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.

要在可观察端实现此机制-使用双重分发模式:

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天全站免登陆