[C++实现 设计模式(12)] : 策略模式

16 篇文章 0 订阅

情景描述

       三国时期 , 诸葛亮气周瑜的过程中 , 有一件事 : 那就是周瑜赔了夫人又折兵这件事 . 在刘备去东吴招亲之前 , 特授以伴郎赵云三个锦囊 , 这三个锦囊分别是 : 找乔国老帮忙 , 求吴国太放行以及孙夫人断后.在这个场景中 , 三个妙计都有了 , 还缺两个配角 : 第一 , 承装妙计的锦囊 ; 第二 , 执行妙计的人.

实现代码如下 :

#include<iostream>
#include<string>
//#include<vld.h>

using namespace std;

//策略模式
#if 0
//妙计接口
class IStrategy
{
public:
	virtual void operate() = 0;
};

//乔国老开后门
class BackDoor : public IStrategy
{
public:
	void operate()
	{
		cout<<"找乔国老帮忙 , 让吴国太给孙尚香施加压力"<<endl;
	}
};

//吴国太开绿灯
class GivenGreeLight : public IStrategy
{
public:
	void operate()
	{
		cout<<"求吴国太开绿灯 , 放行!"<<endl;
	}
};

//孙夫人断后
class BlockEney : public IStrategy
{
public:
	void operate()
	{
		cout<<"孙夫人断后 , 挡住追兵"<<endl;
	}
};

//锦囊
class Context
{
public:
	//构造函数 , 你要使用哪个妙计
	Context(IStrategy* str = nullptr)
	{
		strategy = str;
	}
	//使用计谋了 , 看我出招了
	void operate()
	{
		strategy->operate();
	}
	~Context()
	{
		if(strategy != nullptr)
			delete strategy;
	}
private:
	IStrategy* strategy;
};


//使用计谋
//赵云出场 , 他根据诸葛亮的交代 ,依次拆开锦囊
int main()
{
	Context* context;
	//刚刚到吴国的时候拆第一个
	cout<<"-----------刚刚到吴国的时候拆第一个----------"<<endl;
	//拿到妙计
	context = new Context(new BackDoor());
	//开始执行
	context->operate();
	delete context;
	//刘备乐不思蜀了 , 拆第二个了
	cout<<"-----------刘备乐不思蜀了 , 拆第二个----------"<<endl;
	context = new Context(new GivenGreeLight());
	//执行第二个锦囊
	context->operate();
	delete context;
	//孙权的小兵追来了 , 咋办? 拆第三个
	cout<<"-----------孙权的小兵追来了 , 咋办? 拆第三个----------"<<endl;
	context = new Context(new BlockEney());
	//孙夫人退兵
	context->operate();
	delete context;


	return 0;
}

#endif

运行结果 :
在这里插入图片描述

策略模式的定义

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

策略模式的通用类图 :
在这里插入图片描述

策略模式的结构 :

  • Context封装角色
    也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用 .
  • Strategy抽象策略角色
    通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式 .
  • ContextStrategy具体策略
    具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换 .

策略模式的应用

策略模式的优点
  • 算法可以自由切换
    这是策略模式本身定义的,只要实现抽象策略,它就成为策略家族的一个成员, 通过封装角色对其进行封装,保证对外提供“可自由切换”的策略 .
  • 避免使用多重条件判断
    如果没有策略模式,我们想想看会是什么样子?一个策略家族有5个策略算法,一会要使用A策略,一会要使用B策略,怎么设计呢?使用多重的条件语句?多重条件语句不易维护,而且出错的概率大大增强 . 使用策略模式后,可以由其他模块决定采用何种策略,策略家族对外提供的访问接口就是封装类,简化了操作,同时避免了条件语句判断 .
  • 扩展性良好
    这甚至都不用说是它的优点,因为它太明显了 . 在现有的系统中增加一个策略太容易了,只要实现接口就可以了,其他都不用修改,类似于一个可反复拆卸的插件,这大大地符合了OCP原则 .
策略模式的缺点
  • 策略类数量增多
    每一个策略都是一个类,复用的可能性很小,类数量增多 .
  • 所有的策略类都需要对外暴露
    上层模块必须知道有哪些策略,然后才能决定使用哪一个 策略,这与迪米特法则是相违背的,我只是想使用了一个策略,我凭什么就要了解这个策略呢?那要你的封装类还有什么意义?这是原装策略模式的个缺点, 幸运的是,我们可以使用其他模式来修正这个缺陷,如工厂方法模式、代理模式或享元模式 .
策略模式的使用场景
  • 多个类只有在算法或行为上稍有不同的场景 .
  • 算法需要自由切换的场景 .
    例如,算法的选择是由使用者决定的,或者算法始终在进化,特别是一些站在技术前沿的行业,连业务专家都无法给你保证这样的系统规则能够存在多长时间,在这种情况下策略模式是你最好的助手 .
  • 需要屏蔽算法规则的场景 .
    现在的科技发展得很快,人脑的记忆是有限的(就目前来说是有限的),太多的算法你只要知道一一个名字就可以了,传递相关的数字进来,反馈一个运算结果,万事大吉 .
策略模式的注意事项

       如果系统中的一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题,否则日后的系统维护就会成为一个烫手山芋,谁都不想接 .

总结

       它与模版方法模式的区别在于在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了封装类Context中,抽象策略Strategy一般是一个接口,目的只是为了定义规范,里面一般不包含逻辑 . 其实,这只是通用实现,而在实际编程中,因为各个具体策略实现类之间难免存在一些相同的逻辑,为了避免重复的代码,我们常常使用抽象类来担任Strategy的角色,在里面封装公共的代码,因此,在很多应用的场景中,在策略模式中一般会看到模版方法模式的影子 .

参考书籍 :

                  <<设计模式之禅 第二版>>
                  <<设计模式>>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值