【C++设计模式】策略模式

背景

策略模式(Strategy模式)是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法(策略)选择交由客户端决定。Strategy模式主要用来平滑地处理算法的切换 。
策略模式的UML类图如下,主要的类有三个:
1.抽象策略类Strategy,定义所有支持的算法的公共接口;
2.具体策略类StrategyA,StrategyB,封装具体的算法;
3.上下文Constext类,根据策略类的配置,通过多态实现不同算法的调用
在这里插入图片描述下面例子以计算0到某个正整数的和SumUntil两种算法来体现策略模式:

class SumUntilStrategy
{
public:
	virtual ~SumUntilStrategy() {};
	virtual size_t calSumUntilPara(size_t para) = 0;
};

class SumUntilStrategyNormal : public SumUntilStrategy
{
public:
	size_t calSumUntilPara(size_t para) override {
		size_t sum = 0;
		for (size_t i = 0; i < para + 1; i++) {
			sum += i;
		}
		return sum;
	}
};

class SumUntilStrategyFast : public SumUntilStrategy
{
public:
	size_t calSumUntilPara(size_t para) override {
		return (0 + para) * (para + 1)/2;
	}
};

class SumUntilContext
{
public:
	SumUntilContext(SumUntilStrategy* sumUntil);
	~SumUntilContext();
	size_t sumUntilRet(size_t para);
private:
	SumUntilStrategy* _sumUntil;
};

SumUntilContext::SumUntilContext(SumUntilStrategy * sumUntil)
	: _sumUntil(sumUntil)
{
}

SumUntilContext::~SumUntilContext()
{
	if (_sumUntil) {
		delete _sumUntil;
		_sumUntil = NULL;
	}
}

size_t SumUntilContext::sumUntilRet(size_t para)
{
	if (_sumUntil) {
		return _sumUntil->calSumUntilPara(para);
	}
	return -1;
}

int main()
{
	// 笨算法累加
	SumUntilContext *sumUntil = new SumUntilContext(new SumUntilStrategyNormal());
	size_t ret = sumUntil->sumUntilRet(100);
	delete sumUntil;
	sumUntil = NULL;
	// 类似梯形面积计算的简化算法
	sumUntil = new SumUntilContext(new SumUntilStrategyFast());
	ret = sumUntil->sumUntilRet(99);
	delete sumUntil;
	sumUntil = NULL;
	return 0;
}

写完后发现,用这种策略模式客户端还是需要认识两种不同的策略类名SumUntilStrategyNormal和SumUntilStrategyFast,能不能让客户端不感知这些呢?可以设定两个枚举,修改SumUntilContext的构造函数,不再传入SumUntilStrategy指针,而是在构造函数中通过传入的枚举来决定如何初始化_sumUntil成员,代码如下(只展示了修改的函数,其他和上面的示例代码保持一致):

enum SumUntilWays
{
	SUM_UNTIL_NORMAL,
	SUM_UNTIL_FAST
};

class SumUntilContext
{
public:
	SumUntilContext(SumUntilWays way); // 构造函数不再传入指针而是枚举
	~SumUntilContext();
	size_t sumUntilRet(size_t para);
private:
	SumUntilStrategy* _sumUntil;
};

SumUntilContext::SumUntilContext(SumUntilWays way)
{
	switch (way) {
	case SUM_UNTIL_NORMAL:
		_sumUntil = new SumUntilStrategyNormal();
		break;
	case SUM_UNTIL_FAST:
		_sumUntil = new SumUntilStrategyFast();
		break;
	default:
		_sumUntil = NULL;
		break;
	}
}

int main()
{
	// 客户端只需要认识SumUntilContext类和要使用的方法枚举SumUntilWays即可
	SumUntilContext *sumUntil = new SumUntilContext(SUM_UNTIL_NORMAL);
	size_t ret = sumUntil->sumUntilRet(100);
	delete sumUntil;
	sumUntil = NULL;
	sumUntil = new SumUntilContext(SUM_UNTIL_FAST);
	ret = sumUntil->sumUntilRet(99);
	delete sumUntil;
	sumUntil = NULL;
	return 0;
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值