设计模式,策略模式,c++实现

策略模式,又叫政策模式

定义:定义一组算法,将每个算法都封装起来,并使它们之间可以互换。

这里说到的算法就是函数;
封装起来就是用基类声明虚函数,用子类继承并实现功能;
可以互换表示必须用基类作为与外部调用模块的耦合,而不使功能类与外部产生耦合;
这种模式充分利用了对接口基类的继承,也导致了类数量的增多和复用性的减弱。

当调用模块需要用到某种策略时,只需要临时生成一个该策略对象调用即可,一个执行模块对应多个策略。

类图摘自设计模式之禅,如下:
设计模式,策略模式,c++实现
优点
通过对基类策略action()的封装,子类的扩展,保证了对外提供“可*切换”的策略。

要啥用啥,避免使用大量判断。

扩展性好,只要实现接口就可,如一个可反复拆卸的插件。

缺点
每个策略都是一个类,导致类的数量多,复用性差。

所有策略类都对外暴露,因为上层模块需要知道策略的作用然后在考虑使用,违背了迪米特法则,但可以通过其他设计模式修正该缺陷。

使用场景
多个类只在算法上有差异,如筛选过程(筛选标准可作为算法策略)

算法需要*切换的场景,算法的选择由使用者决定,或算法本身在不断进化,如灯光颜色类型(rgb,CMYK等可作为策略)等。

需要屏蔽算法规则的场景,如传个数字给个结果,不想知道过程和原因时。

注意事项
如果策略家族数量超过4个,就需要考虑混合模式,解决策略类膨胀和对外暴露的问题,否则维护难度很大。

代码示例:张三面对不同对象时的不同应对策略

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 << "你好啊儿子" << endl;
	}

	void DoSomethingForSon()
	{
		cout << "来零花钱拿着" << endl;
	}

	void ByeToSon()
	{
		cout << "快回家,注意安全啊" << endl;
	}
};

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

private:
	void SaySomethingToWife()
	{
		cout << "老婆好,今天好漂亮" << endl;
	}

	void DoSomethingForWife()
	{
		cout << "这是我这个月的工资,你帮我保管下可以不" << endl;
	}

	void DoSomethingExtraWithWife()
	{
		cout << "和老婆一起做会运动" << endl;
	}

	void ByeToWife()
	{
		cout << "老婆再见" << endl;
	}
};

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

private:
	void SaySomethingToBoss()
	{
		cout << "老板好" << endl;
	}

	void DoSomethingForBoss()
	{
		cout << "自愿加班干活" << endl;
	}
};

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

	cout << "张三见到了儿子" << endl;
	ZhangSan->SetStrategy(Son);
	ZhangSan->strategy();
	cout << endl;

	cout << "张三见到了老婆" << endl;
	ZhangSan->SetStrategy(Wife);
	ZhangSan->strategy();
	cout << endl;

	cout << "张三见到了老板" << endl;
	ZhangSan->SetStrategy(Boss);
	ZhangSan->strategy();
	cout << endl;
}

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

设计模式,策略模式,c++实现
通过策略模式达到了多态,如果还有其他策略,也可以通过继承Strategy继续扩展,扩展性良好。
同时每个策略的详细实现都不一样,类中具体的扩展全部设置为private,达到高内聚的要求。
只通过action()与调用模块耦合,达到了低耦合的要求。
调用模块不需要知道策略干了什么,只需要调用策略就可以,很方便。

上一篇:使用vuex中的action发送请求


下一篇:Redux官网学习知识点(day2):useSelector、useDispatch、createAsyncThunk、createSlice