Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.02 KB | None | 0 0
  1. #ifndef OBSERVER_H
  2. #define OBSERVER_H
  3.  
  4. #include <set>
  5. #include <functional>
  6.  
  7. /**
  8.  * @class Observer
  9.  *
  10.  * Implementation of basic observer functional
  11.  *
  12.  * Usage:
  13.  *
  14.  * class TestObservedObjectDelegate
  15.  * {
  16.  * public:
  17.  *     virtual void onPropertyChanged(int value) {}
  18.  * };
  19.  *
  20.  * class TestObservedObject: public Observed<TestObservedObjectDelegate>
  21.  * {
  22.  *     int m_property = 0;
  23.  * public:
  24.  *     int property() const { return m_property; }
  25.  *     void setPropery(int value)
  26.  *     {
  27.  *         if (m_property == value) return;
  28.  *         m_property = value;
  29.  *         visitDelegates(&TestObservedObjectDelegate::onPropertyChanged, m_property);
  30.  *     }
  31.  * };
  32.  *
  33.  * class HandlePropChanged: public TestObservedObjectDelegate
  34.  * {
  35.  *     TestObservedObject m_observedObject;
  36.  * public:
  37.  *     HandlePropChanged()
  38.  *     {
  39.  *         m_observedObject.addDelegate(this);
  40.  *     }
  41.  *     ~HandlePropChanged()
  42.  *     {
  43.  *         m_observedObject.removeDelegate(this);
  44.  *     }
  45.  *     void onPropertyChanged(int value)
  46.  *     {
  47.  *         // handle on property changed
  48.  *     }
  49.  * };
  50.  *
  51.  *
  52.  */
  53.  
  54.  
  55. template<typename Delegate>
  56. class Observer
  57. {
  58. public:
  59.  
  60.  
  61.     /**
  62.      * @brief hasDelegate
  63.      *
  64.      * Check
  65.      *
  66.      * @param delegate
  67.      * @return true,
  68.      */
  69.     bool hasDelegate(Delegate* delegate)
  70.     {
  71.         if (delegate == nullptr) return false;
  72.         return m_delegates.find(delegate) != m_delegates.end();
  73.     }
  74.  
  75.     /**
  76.      * @brief addDelegate
  77.      *
  78.      * Added @class Delegate pointer to observer
  79.      *
  80.      * @param delegate
  81.      */
  82.     void addDelegate(Delegate* delegate)
  83.     {
  84.         if (delegate == nullptr) return;
  85.         if (!hasDelegate(delegate))
  86.         {
  87.             m_delegates.insert(delegate);
  88.         }
  89.     }
  90.  
  91.     /**
  92.      * @brief removeDelegate
  93.      *
  94.      * Remove @param delegate pointer if observer has @param delegate pointer
  95.      *
  96.      * @param delegate
  97.      */
  98.     void removeDelegate(Delegate* delegate)
  99.     {
  100.         if (delegate == nullptr) return;
  101.         if (hasDelegate(delegate))
  102.         {
  103.             m_delegates.erase(delegate);
  104.         }
  105.     }
  106.  
  107.     /**
  108.      * @brief visitDelegates
  109.      *
  110.      * Call function @param visitor for all delegates
  111.      *
  112.      * @param visitor
  113.      */
  114.     template<typename Lambda=std::function<void(Delegate*)>>
  115.     void visitDelegates(Lambda visitor)
  116.     {
  117.         for (auto delegate: m_delegates) {
  118.             std::invoke(visitor, delegate);
  119.         }
  120.     }
  121.  
  122.     template<typename Method, typename ...Args>
  123.     void visitDelegates(Method method, Args&& ...args)
  124.     {
  125.         for (auto delegate: m_delegates) {
  126.             std::invoke(method, delegate, std::forward<Args>(args)...);
  127.         }
  128.     }
  129.  
  130.     /**
  131.      * @brief size
  132.      * @return
  133.      */
  134.     size_t size()
  135.     {
  136.         return m_delegates.size();
  137.     }
  138.  
  139. private:
  140.     std::set<Delegate*> m_delegates;
  141. };
  142.  
  143. /**
  144.  * @brief The Observed class
  145.  *
  146.  * Basic implementation of observed object
  147.  */
  148. template<typename Delegate>
  149. class Observed
  150. {
  151. public:
  152.     virtual ~Observed() = default;
  153.     virtual bool hasDelegate(Delegate* delegate) { return  m_observer.hasDelegate(delegate); }
  154.     virtual void addDelegate(Delegate* delegate) { m_observer.addDelegate(delegate); }
  155.     virtual void removeDelegate(Delegate* delegate) { m_observer.removeDelegate(delegate); }
  156.  
  157. protected:
  158.     template<typename Lambda=std::function<void(Delegate*)>>
  159.     void visitDelegates(std::function<void(Delegate*)> visitor)
  160.     {
  161.         m_observer.visitDelegates(visitor);
  162.     }
  163.  
  164.     template<typename Method, typename ...Args>
  165.     void visitDelegates(Method method, Args&& ...args) {
  166.         m_observer.visitDelegates(method, args...);
  167.     }
  168.  
  169.     Observer<Delegate>& observer() { return m_observer; }
  170.  
  171. private:
  172.     Observer<Delegate> m_observer;
  173. };
  174.  
  175. #define SETTER_BODY(field, value, notify) \
  176.     if (field == value) return; \
  177.     field = value; \
  178.     visitDelegates(notify, this, field); \
  179.  
  180.  
  181. #endif // OBSERVER_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement