Design pattern, policy pattern, c + + implementation

Keywords: C++ Design Pattern

Strategic model, also known as policy model

Definition: define a set of algorithms, encapsulate each algorithm and make them interchangeable.

The algorithm mentioned here is a function;
Encapsulation is to declare virtual functions with base classes, inherit and implement functions with Subclasses;
Interchangeability means that the base class must be used as the coupling with the external calling module without coupling the functional class with the external;
This pattern makes full use of the inheritance of the interface base class, which also leads to the increase of the number of classes and the weakening of reusability.

When the calling module needs to use a policy, it only needs to temporarily generate a call of the policy object, and an execution module corresponds to multiple policies.

The class diagram is taken from the Zen of design pattern, as follows:

advantage:
The encapsulation of the base class policy action() and the extension of subclasses ensure that the policy of "free switching" is provided externally.

Use what you want and avoid using a lot of judgment.

Good expansibility, as long as the interface is implemented, such as a repeatedly removable plug-in.

Disadvantages:
Each policy is a class, resulting in a large number of classes and poor reusability.

All policy classes are exposed to the outside world, because the upper module needs to know the role of the policy and then consider its use, which violates the Demeter's law, but the defect can be corrected through other design patterns.

Usage scenario:
Multiple classes differ only in algorithm, such as filtering process (filtering criteria can be used as algorithm strategy)

The algorithm needs to freely switch scenes. The choice of the algorithm is determined by the user, or the algorithm itself is evolving, such as light color type (rgb, CMYK, etc. can be used as a strategy), etc.

Scenarios that need to mask algorithm rules, such as passing a number to a result, and do not want to know the process and reason.

matters needing attention:
If the number of policy families exceeds 4, it is necessary to consider the mixed mode to solve the problems of policy class expansion and external exposure. Otherwise, it is very difficult to maintain.

Code example: Zhang San's different coping strategies when facing different objects

class Strategy
{
public:
	virtual void action() = 0;
};

class Context
{
public:
	void SetStrategy(Strategy* strategy)
	{
		mStrategy = strategy;
	}

	void strategy()
	{
		mStrategy->action();
	}

protected:
	Strategy* mStrategy;
};

class MeetSon:public Strategy
{
public:
	virtual void action()
	{
		SaySomethingToSon();
		DoSomethingForSon();
		ByeToSon();
	}

private:
	void SaySomethingToSon()
	{
		cout << "Hello, son" << endl;
	}

	void DoSomethingForSon()
	{
		cout << "Take your pocket money" << endl;
	}

	void ByeToSon()
	{
		cout << "Go home and be safe" << endl;
	}
};

class MeetWife :public Strategy
{
public:
	virtual void action()
	{
		SaySomethingToWife();
		DoSomethingForWife();
		DoSomethingExtraWithWife();
		ByeToWife();
	}

private:
	void SaySomethingToWife()
	{
		cout << "Good wife. It's beautiful today" << endl;
	}

	void DoSomethingForWife()
	{
		cout << "This is my salary this month. Can you keep it for me" << endl;
	}

	void DoSomethingExtraWithWife()
	{
		cout << "Do sports with your wife" << endl;
	}

	void ByeToWife()
	{
		cout << "Bye, wife" << endl;
	}
};

class MeetBoss :public Strategy
{
public:
	virtual void action()
	{
		SaySomethingToBoss();
		DoSomethingForBoss();
	}

private:
	void SaySomethingToBoss()
	{
		cout << "Hello, boss" << endl;
	}

	void DoSomethingForBoss()
	{
		cout << "Volunteer to work overtime" << endl;
	}
};

void func()
{
	Context* ZhangSan = new Context();
	Strategy* Son = new MeetSon();
	Strategy* Wife = new MeetWife();
	Strategy* Boss = new MeetBoss();

	cout << "Zhang San saw his son" << endl;
	ZhangSan->SetStrategy(Son);
	ZhangSan->strategy();
	cout << endl;

	cout << "Zhang San saw his wife" << endl;
	ZhangSan->SetStrategy(Wife);
	ZhangSan->strategy();
	cout << endl;

	cout << "Zhang San met his boss" << endl;
	ZhangSan->SetStrategy(Boss);
	ZhangSan->strategy();
	cout << endl;
}

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


Polymorphism is achieved through the policy mode. If there are other policies, they can also continue to expand by inheriting Strategy, with good scalability.
At the same time, the detailed implementation of each strategy is different. All the specific extensions in the class are set to private to meet the requirements of high cohesion.
It is only coupled with the calling module through action(), which meets the requirement of low coupling.
The calling module does not need to know what the policy does. It only needs to call the policy, which is very convenient.

Posted by Woolf on Sat, 16 Oct 2021 00:47:40 -0700