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)
如果传感器类型的数量或多或少稳定(而且确实如此 - 在大多数情况下变化非常罕见) - 那么只需在观察者端做好准备以获得几种类型的通知:
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)
它在实践中如何运作,请参阅现场演示