Design pattern, detailed explanation of responsibility chain pattern, c + + implementation

Keywords: C++ Design Pattern

Detailed explanation of responsibility chain mode, c + + implementation

Responsibility chain model
Definition: multiple objects have the opportunity to process the request, avoid the coupling relationship between the sender and receiver of the request, connect the processing objects into a chain, and pass the request along the chain until an object processes it.
The focus is on the "chain". A chain handles similar requests and determines who will handle the request in the chain. It is suitable for dealing with requirements with hierarchical restrictions.

General class diagram

The Handler has three responsibilities:
1. Define a request processing level judgment method handle() to judge whether to process or push to the next level. This should be the only method open to the outside world by the processor. It should be modified with final so that it will not be changed. Because the level judgment function is determined in the base class, the template mode is also used.
2. Define the arrangement method of a chain. setNext() is used to set the next level of the "chain".
3. Define your own processing level and the solution to the request echo().

advantage:
Separate the request and processing. The requester does not need to know who handles it, and the processor does not need to know who requests it. The two are decoupled to improve the flexibility of the system.

Disadvantages:
There are two obvious points. One is performance. Each request is traversed from beginning to end. If the chain is very long, it is very inconvenient; Second, the debugging is inconvenient. The recursive method is used to judge the processing level, and the logic is complex. The time and memory loss caused by recursion will be significantly increased due to the lengthening of the chain.

matters needing attention:
Due to significant shortcomings, we should pay most attention to controlling the number of chain nodes. Generally, we can set a maximum number of nodes in the base class and judge whether it exceeds the threshold in the setNext() method. If it exceeds the threshold, the chain is not allowed to be established to avoid unintentional damage to the system performance.

c + + code example

//A requirement class is a class to be processed
class request
{
public:
	request(string& Data, const int& HandlerLevel)
	{
		mstrData = Data;
		miHandlerLevel = HandlerLevel;
		cout << "Task created with processing level" << miHandlerLevel << endl;
	}

	int getHandlerLevel()
	{
		return miHandlerLevel;
	}

	void setHandlerLevel(int &HandlerLevel)
	{
		miHandlerLevel = HandlerLevel;
	}

	string getData()
	{
		return mstrData;
	}

protected:
	int miHandlerLevel;
	string mstrData;
};

//The base class of the processing class, determines the processing level, and uses subclasses to realize the specific way of processing requirements
class handler
{
public:
	handler(const int& handlerLevel) :miHandlerLevel(handlerLevel), mNext(nullptr)
	{

	}

	void Judge_Handle(request* Request)
	{
		if (getHandlerLevel() == Request->getHandlerLevel())
		{
			handle(Request);
		}
		else if(mNext != nullptr)
		{
			cout << "This level cannot be processed and submitted to the next one" << endl;
			mNext->Judge_Handle(Request);
		}
		else
		{
			cout << "The command cannot be processed" << endl;
		}
	}

	void setNext(handler* Handler)
	{
		mNext = Handler;
	}

protected:
	virtual void handle(request* Request)
	{

	}

	int getHandlerLevel()
	{
		return miHandlerLevel;
	}

	handler* mNext;
	int miHandlerLevel;
};

class employee :public handler
{
public:
	employee(const int& handlerLevel):handler(handlerLevel)
	{
		cout << "Handler created, level" << miHandlerLevel << endl;
	}

protected:
	virtual void handle(request* Resquest)
	{
		cout << Resquest->getData() << "The treatment level is" << Resquest->getHandlerLevel() << ",Has been" << getHandlerLevel() << "Grade handling personnel" << endl;
	}
};

//Test function
void func()
{
	//Determine grade
	const int LEVEL1 = 1;
	const int LEVEL2 = 2;
	const int LEVEL3 = 3;
	const int LEVEL4 = 4;

	//Combined processing chain
	handler* Handler1 = new employee(LEVEL1);
	handler* Handler2 = new employee(LEVEL2);
	handler* Handler3 = new employee(LEVEL3);
	Handler1->setNext(Handler2);
	Handler2->setNext(Handler3);

	//Generate requirements of different levels
	string data = "mission1";
	request* Request1 = new request(data, LEVEL1);
	data = "mission2";
	request* Request2 = new request(data, LEVEL2);
	data = "mission3";
	request* Request3 = new request(data, LEVEL3);
	data = "mission4";
	request* Request4 = new request(data, LEVEL4);

	//Just let the first person in the processing chain handle all tasks
	Handler1->Judge_Handle(Request1);
	Handler1->Judge_Handle(Request2);
	Handler1->Judge_Handle(Request3);
	Handler1->Judge_Handle(Request4);
}

int main()
{
	func();
	return 0;
}

Posted by yorktown on Sat, 09 Oct 2021 21:26:48 -0700