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

前端之家收集整理的这篇文章主要介绍了c – 如何在Observer中处理具有不同状态值类型的Observable前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
(上下文和问题,帖子底部的骨架代码)

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

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

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

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

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

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

编辑:请注意,dynamic_cast<>由于Arduino的限制,结构是不可能的

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

  1. class SenseNode
  2. {
  3. public:
  4. SenseNode() {};
  5. SenseNode(uint8_t aNodeId): id(aNodeId) {}
  6. virtual ~SenseNode() {}
  7.  
  8. uint8_t getId() { return id; };
  9. private:
  10. uint8_t id = 0;
  11. };
  12.  
  13. class SenseStateNode : virtual public SenseNode
  14. {
  15. public:
  16. SenseStateNode(uint8_t aNodeId) : SenseNode(aNodeId) {}
  17. virtual ~SenseStateNode() {}
  18.  
  19. /** Return current node state interpreted as an integer. */
  20. virtual int getValueAsInt();
  21. };
  22.  
  23. class SenSEObservable: public SenseStateNode
  24. {
  25. public:
  26. SenSEObservable(uint8_t aNodeId);
  27. virtual ~SenSEObservable();
  28. /** Notify all interested observers of the change in state by calling Observer.notification(this) */
  29. virtual void notifyObservers();
  30. protected:
  31. virtual void registerObserver(SenSEObserver *);
  32. virtual void unregisterObserver(SenSEObserver *);
  33. };
  34.  
  35. class SenSEObserver: virtual public SenseNode
  36. {
  37. public:
  38. SenSEObserver() {};
  39. virtual ~SenSEObserver();
  40.  
  41. /** Called by an Observable that we are observing to inform us of a change in state */
  42. virtual void notification(SenSEObservable *observable) {
  43. int v = observable->getValueAsInt(); // works like a charm
  44. DateTime d = observable-> ???? // How should i solve this elegantly?
  45. };
  46. };

解决方法

如果传感器类型的数量或多或少稳定(并且它是 – 在大多数情况下变化非常罕见) – 那么只需在Observer端准备以获得几种通知
  1. class Observer
  2. {
  3. public:
  4. virtual void notify(SenseNode& node) {
  5. // implement here general actions - like printing: not interested in this
  6.  
  7. }
  8. virtual void notify(RealTimeClock& node) {
  9. notify(static_cast<SenseNode&>(node));
  10. // by default go to more general function
  11. }
  12. // and follow this pattern - for all nodes you want to handle
  13. // add corresponding notify(T&) function
  14. };

当它发生时你必须添加新的节点类型 – 然后只需将新的虚函数添加到你的基础Observer类.

要在Observable端实现此机制 – 使用double dispatch pattern

  1. class SenseNode {
  2. public:
  3. virtual void notifyObserver(Observer& observer) {
  4. observer.notify(*this);
  5. }
  6. };
  7.  
  8. class RealTimeClock : public virtual SenseNode {
  9. public:
  10. virtual void notifyObserver(Observer& observer) {
  11. observer.notify(*this);
  12. // this will select proper Observer::notify(RealTimeClock&)
  13. // because *this is RealTimeCLock
  14. }
  15. };
  16.  
  17.  
  18. class SenSEObservable: public SenseStateNode
  19. {
  20. public:
  21. virtual void notifyObservers() {
  22. for (auto& observer : observers)
  23. notifyObserver(observer);
  24. }
  25. };

它在实践中如何运作,见live demo

猜你在找的C&C++相关文章