Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>One quick thought:</strong></p> <p>1) Observer pattern between composite and atomic states ("a", "b", "c" as observees and "A" as observer, so on..)</p> <p>2) Have class-A implemented using Pimpl idiom to separate the interface &amp; implementation details, thus have more control and exhibit more flexibily in changing the implementation details.</p> <p>3) Let class-A have some kind of Factory abstraction to create &amp; manage specialized implementation-objects for each unique state of "A".</p> <p>4) Thus, whenever changes on a, b, c are observed by "A", Factory helps to retrieve the corresponding implementation-state of "A" and does a state change. Apply same approach between "A" and "X".</p> <p><strong>More detailed layout:</strong></p> <p>1) Define the required interfaces (generic or abstract classes) IX, IA, Ia, Ib, Ic.</p> <p>2) In interface IA, define public IaChanged(Ia*), IbChanged(Ib*) &amp; IcChanged(Ic*) methods to receive Ia, Ib &amp; Ic state change notifications (Callback methods of Observer pattern).</p> <p>3) Inside the atomic interfaces Ia, Ib &amp; Ic. Define public Register(IA&amp;) &amp; private Notify() metods. In Interface Ia,</p> <pre><code> Where Notify() { foreach(observer in m_Observers) observer-&gt;IaChanged(this); } </code></pre> <p>In Interface Ib,</p> <pre><code> Where Notify() { foreach(observer in m_Observers) observer-&gt;IbChanged(this); } </code></pre> <p>so on...</p> <p>4) Have clases X, A, a, b, c derived from respective interfaces. X->IX, A->IA, a->Ia, b->Ib &amp; c->Ic, where -> represents "derives".</p> <p>5) Have class A define A_implState (Pimpl Idiom), where A_implState may derive from a new interface IA_implState to keep things generic.</p> <p>Have classes A_implState0, A_implState1, A_implState2, A_implStateX as specialized versions of IA_implState.</p> <p>where,</p> <pre><code> class IA_implState { public: virtual void processStateChange()=0; }; class A_implState0 : public IA_implState { public: void processStateChange() { // do your stuff specific to State "0" of "A". } }; class A_implStateX : public IA_implState { public: void processStateChange() { // do your stuff specific to State "X" of "A". } }; so on... </code></pre> <p>6) Have one specialization of IA_Impl for each distinct states of A, based on: </p> <pre><code>a b c - A 0 0 0 - 0 1 0 0 - 1 2 0 0 - x 2 1 0 - 2 </code></pre> <p>7) In class A, whenever IaChanged(IaPtr) or IbChanged(IbPtr) or IcChanged(IcPtr) gets triggered by respective observee, process the change notifications as:</p> <pre><code> // a changed void A::IaChanged(IaPtr a) { //Buffer Ia inside a member m_pIa = a; //Retrieve A-implementer based on the current state. m_pimplA = m_implAContainer[GetCurrentState()]; // or use FactoryMethod or AbstractFactory pattern if required. m_pimplA-&gt;processStateChange(); } // b changed void A::IbChanged(IbPtr b) { //Buffer Ib inside a member m_pIb = b; m_pimplA = m_implAContainer[GetCurrentState()]; // use FactoryMethod or AbstractFactory pattern if required. m_pimplA-&gt;processStateChange(); } </code></pre> <p><strong>/* a rough sketch, may look like */</strong></p> <p>use shared_pointers for managing lifetime, define some typedefs for ease of use.</p> <pre><code> typedef std::shared_ptr&lt;Ia&gt; IaPtr; typedef std::shared_ptr&lt;Ib&gt; IbPtr; typedef std::shared_ptr&lt;IA_impl&gt; IAImplPtr; typedef std::map&lt;int /* or other datatype as required */ , IA_implPtr&gt; ImplAPtrContainer; // class-A may look like class A : public IA { public: void IaChanged(const IaPtr ptr_a); void IbChanged(const IbPtr ptr_b); void Init(); void DeInit() { m_implAContainer.clear(); } private: int GetCurrentState(); private: ImplAPtrContainer m_implAContainer; IAImplPtr m_pimplA; IaPtr m_aPtr; IbPtr m_bPtr; IcPtr m_cPtr; }; </code></pre> <p><em>// Initialize Container with all possible implementation states for class-A</em></p> <pre><code> void A::Init() { m_implAContainer.insert(/*state*/ 0, IAImplPtr(new A_implState0)); m_implAContainer.insert(/*state*/ 1, IAImplPtr(new A_implState1)); m_implAContainer.insert(/*state*/ X, IAImplPtr(new A_implStateX)); } </code></pre> <p><em>// Determine the A's current state based on a, b &amp; c' current state</em></p> <pre><code> int A::GetCurrentState() { // Have this method return A's state based on a b c, prefer enums over magic numbers if(m_aPtr-&gt;GetState() == 0 &amp;&amp; m_bPtr-&gt;GetState() == 0 &amp;&amp; m_cPtr-&gt;GetState() == 0) return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload