C + + design pattern observer pattern

Keywords: Excel less

Observer mode

In GOF's "design pattern: the foundation of reusable object-oriented software", the observer pattern is said as follows: define a one to many dependency between objects. When the state of an object changes, all objects that depend on it are notified and automatically updated. When an object changes, the object following it is notified; this interaction is also known as publish subscribe. The target is the publisher of the notification, and it doesn't need to know who its observers are when it issues the notification.

In addition, the relationship between the above data and graphs; whether it's a line chart, pie chart or histogram, they all depend on data; when the data changes, the data object will notify the object that depends on it to update; so in Excel, when the data changes, the corresponding statistical chart will be automatically redrawn.

 

UML class diagram

Subject (target)
——The target knows its observer. Any number of observers can observe the same target;
——Provides an interface for registering and deleting observer objects.

Observer
——Define an update interface for those objects that need to be notified when the target changes.

ConcreteSubject (specific target)
——Store the relevant state into each ConcreteObserver object;
——When its state changes, it notifies its observers.

ConcreteObserver
——Maintain a reference to the ConcreteSubject object;
——Store relevant States, which shall be consistent with the state of the target;
——Implement the update interface of the Observer to keep its state consistent with that of the target.

The observer model works together in the following ways:

  1. When any change occurs to the concrete subject that may cause its observers to be inconsistent with its own state, it will notify its observers;
  2. After getting a change notice of a specific target, the ConcreteObserver object can query the target object for information. ConcreteObserver uses this information to make its state consistent with the state of the target object.

Here is the call sequence diagram:

 

Use occasion

Observer mode can be used in any of the following cases:

  1. When an abstract model has two aspects, one depends on the other. They are encapsulated in independent objects so that they can be changed and reused independently;
  2. When the change of one object needs to change other objects at the same time, without knowing how many objects need to be changed;
  3. When an object has to notify other objects, it cannot assume who they are; that is, you do not want them to be tightly coupled.

 

code implementation

#include <iostream>
#include <list>
using namespace std;
 
class Observer
{
public:
     virtual void Update(int) = 0;
};
 
class Subject
{
public:
     virtual void Attach(Observer *) = 0;
     virtual void Detach(Observer *) = 0;
     virtual void Notify() = 0;
};
 
class ConcreteObserver : public Observer
{
public:
     ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){}
 
     void Update(int value)
     {
          cout<<"ConcreteObserver get the update. New State:"<<value<<endl;
     }
 
private:
     Subject *m_pSubject;
};
 
class ConcreteObserver2 : public Observer
{
public:
     ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){}
 
     void Update(int value)
     {
          cout<<"ConcreteObserver2 get the update. New State:"<<value<<endl;
     }
 
private:
     Subject *m_pSubject;
};
 
class ConcreteSubject : public Subject
{
public:
     void Attach(Observer *pObserver);
     void Detach(Observer *pObserver);
     void Notify();
 
     void SetState(int state)
     {
          m_iState = state;
     }
 
private:
     std::list<Observer *> m_ObserverList;
     int m_iState;
};
 
void ConcreteSubject::Attach(Observer *pObserver)
{
     m_ObserverList.push_back(pObserver);
}
 
void ConcreteSubject::Detach(Observer *pObserver)
{
     m_ObserverList.remove(pObserver);
}
 
void ConcreteSubject::Notify()
{
     std::list<Observer *>::iterator it = m_ObserverList.begin();
     while (it != m_ObserverList.end())
     {
          (*it)->Update(m_iState);
          ++it;
     }
}
 
int main()
{
     // Create Subject
     ConcreteSubject *pSubject = new ConcreteSubject();
 
     // Create Observer
     Observer *pObserver = new ConcreteObserver(pSubject);
     Observer *pObserver2 = new ConcreteObserver2(pSubject);
 
     // Change the state
     pSubject->SetState(2);
 
     // Register the observer
     pSubject->Attach(pObserver);
     pSubject->Attach(pObserver2);
 
     pSubject->Notify();
 
     // Unregister the observer
     pSubject->Detach(pObserver);
 
     pSubject->SetState(3);
     pSubject->Notify();
 
     delete pObserver;
     delete pObserver2;
     delete pSubject;
}

summary

The observer pattern plays a very high role in the 23 design patterns, and we can see it everywhere in all major frameworks. A real understanding of the whole pattern is very helpful for us to understand other people's code; we will use the design pattern more or less in our future work. What is summarized here is not very comprehensive. If I encounter something that needs to be added in the future, I will continue to add it. At the same time, I hope you can put forward better suggestions.

Published 29 original articles, won praise 4, visited 1351
Private letter follow

Posted by mrMarcus on Fri, 17 Jan 2020 01:00:43 -0800