Observer mode of design mode

Observer pattern: defines a one to many dependency between objects, so that whenever the state of an object changes, its related dependent objects are notified and automatically updated. Aliases for observer mode include Publish/Subscribe mode, Model/View mode, Source/Listener mode, or Dependents mode.
Problem solved: one to one or one to many object interaction scenarios.

Implementation technology: virtual function, inheritance, polymorphism, association and aggregation.

The observer mode structure chart includes the following roles:

● Subject: the target is also called Subject, which refers to the observed object. A set of observers is defined in the target. An observation target can be observed by any number of observers. It provides a series of methods to add and delete observer objects. At the same time, it defines the notification method notify(). The target class can be an interface, an abstract class or a concrete class.

● ConcreteSubject (specific target): the specific target is a subclass of the target class, which usually contains data that often changes. When its state changes, it will send a notice to its observers; It also implements the abstract business logic methods (if any) defined in the target class. If there is no need to extend the target class, the specific target class can be omitted.

● Observer: the observer will respond to the change of observation target. The observer is generally defined as an interface, which declares the method of updating data, update(), so it is also called abstract observer.

● ConcreteObserver: maintain a reference to the specific target object in the specific Observer, which stores the relevant states of the specific Observer. These states need to be consistent with the state of the specific target; It implements the update() method defined in the abstract Observer. Usually, during implementation, you can call the attach() method of the specific target class to add yourself to the collection of the target class or delete yourself from the collection of the target class through the detach() method.

The observer pattern describes how to establish dependencies between objects and how to construct a system to meet this demand.

The observer relates to the target, and the target aggregates the observer. In this way, there will be two-way Association, which also needs to be implemented by class and include.

Main advantages

The main advantages of observer mode are as follows:

(1) observer mode can realize the separation of presentation layer and data logic layer, define a stable message update transmission mechanism, and abstract the update interface, so that a variety of different presentation layers can act as specific observers.

(2) observer mode establishes an abstract coupling between the observation target and the observer. The observation target only needs to maintain a collection of abstract observers without understanding its specific observers. Since the observation target and the observer are not closely coupled, they can belong to different levels of abstraction.

(3) the observer mode supports broadcast communication, and the observation target will send a notice to all registered observer objects, which simplifies the difficulty of one to many system design.

(4) the observer mode meets the requirements of the "opening and closing principle". Adding a new specific observer does not need to modify the original system code. It is also convenient to add a new observation target when there is no correlation between the specific observer and the observation target.

Main disadvantages

The main disadvantages of observer mode are as follows:

(1) if an observation target has many direct and indirect observers, it will take a lot of time to notify all observers.

(2) if there is a circular dependency between the observer and the observation target, the observation target will trigger a circular call between them, which may lead to system crash.

(3) the observer model has no corresponding mechanism to let the observer know how the observed target object has changed, but only know that the observed target has changed.

Applicable scenario

(1) an abstract model has two aspects, one of which depends on the other. These two aspects are encapsulated in independent objects so that they can be changed and reused independently.

(2) the change of one object will lead to the change of one or more other objects, and we don't know how many objects will change or who these objects are.

(3) you need to create A trigger chain in the system. The behavior of object A will affect object B, and the behavior of object B will affect object C.. You can use the observer mode to create A chain trigger mechanism.

Extension:

The observer mode is also applied in the current popular MVC (model view Controller) architecture. MVC is an architecture mode, which contains three roles: model, view and controller. The model can correspond to the observation target in the observer mode, while the view corresponds to the observer, and the controller can act as an intermediary between the two.

c + + Example
 

#pragma once
#include <string>
#include <afx.h>

class CSubject;

using namespace std;

//Abstract observation class
class CObserver
{
public:
	string m_name;

	void setName(string name) {
		m_name = name;
	}

	string getName() {
		return m_name;
	}

	virtual void help() {} //Declare ways to support allies
	virtual void beAttacked(CSubject *acc) {} //Attack method statement
};

//Team members: specific observers
class ConcreteObserver :public CObserver
{
public:
	ConcreteObserver(string name) {
		m_name = name;
	}

	//Implementation of support method
	void help() {
		TRACE("hold one's own!%s To save you!\n",m_name.c_str());
	}

	//The implementation of the attacked method will call the notification method notifyObserver() of the team control center class to notify allies when attacked
	void beAttacked(CSubject *acc); 
};

#include "pch.h"
#include "Observer.h"
#include "Subject.h"

void ConcreteObserver::beAttacked(CSubject *acc)
{
	TRACE("%s Attacked!\n", m_name.c_str());
	acc->notifyObserver(m_name);
}
#pragma once
#include <string>
#include <afxtempl.h>

#include <afx.h>
#include "Observer.h"

using namespace std;

class CSubject
{
public:
	string m_allyName; //Team Name 
	CTypedPtrArray<CPtrArray, CObserver*>players;//Define a collection for storing team members
    //CArray<CObserver,CObserver&> players ; // Define a collection for storing team members

	void setAllyName(string allyName) {
		m_allyName = allyName;
	}

	string getAllyName() {
		return m_allyName;
	}

	//Registration method
	void join(CObserver *obs) {
		TRACE("%s join%s Team!\n", obs->getName().c_str(),m_allyName.c_str());
		players.Add(obs);
	}

	//Logout method
	void quit(CObserver obs) {
		TRACE("%s sign out%s Team!\n", obs.getName().c_str(), m_allyName.c_str());
		//players.remove(obs);
	}

	//Declare Abstract notification methods
	virtual void notifyObserver(string name) {};

};


//Specific team control center class: specific target class
class ConcreteSubject :public CSubject {
public:
	ConcreteSubject(string allyName) {
		TRACE( "%s The formation of the team is successful!\n", allyName.c_str());
		m_allyName = allyName;
	}

	//Implementation notification method
	void notifyObserver(string name) {
		TRACE("%s Team emergency notification, ally%s Be attacked by the enemy\n",m_allyName.c_str(),name.c_str());
		//Traverse the set of observers and call the support methods of each ally (except yourself)
		for (int i = 0; i < players.GetSize();i++)
		{
			if (players.GetAt(i)->getName() != name)
			{
				players.GetAt(i)->help();
			}		
		}
	}
};


void TestObserverPattern()
{
	CSubject *acc;
	acc = new ConcreteSubject("Jin Yong Heroes");

	//Define four observer objects
	CObserver *player1, *player2, *player3, *player4;

	player1 = new ConcreteObserver("Guo Yang");
	acc->join(player1);

	player2 = new ConcreteObserver("linghu chong");
	acc->join(player2);

	player3 = new ConcreteObserver("zhang wuji");
	acc->join(player3);

	player4 = new ConcreteObserver("duan yu");
	acc->join(player4);

	//A member is attacked
	player1->beAttacked(acc);

	if (acc)
	{
		delete acc;
	}

	if (player1)
	{
		delete player1;
	}
	if (player2)
	{
		delete player2;
	}
	if (player3)
	{
		delete player3;
	}
	if (player4)
	{
		delete player4;
	}

}


 

Keywords: Design Pattern

Added by sarika on Mon, 07 Feb 2022 09:52:29 +0200