用C++跟你聊聊“策略模式”

时间:2022-07-23
本文章向大家介绍用C++跟你聊聊“策略模式”,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

说实话上一篇的“简单工厂模式”,我觉得不是很满意。 虽然网上大部分都是用Java写的设计模式,但是我竟然是用“伪代码”写的。。

所以我决定,接下来的每篇设计模式都用C++亲测。

一个简单的超市促销活动

现在需要你为商场做一个促销计算器,促销种类包括:不促销、打折、消费返利。

你会如何操作呢?

讨论过了上一节的简单工厂模式,我觉得应该不至于把类设计的太死板了。 但是简单工厂模式有一个明显的缺点,就是会暴露出过多的接口,而且代码重用度也不是很理想的。

不卖关子了啊,题目都写在那儿了,今天我们来聊聊 - ”策略模式“。

要聊”策略模式“,咱首先得有共同语言。昨天讲UML的时候有一个名词我现在还记忆犹新:抽象基类。此时可能一群不了解没听说过或者不了解抽象基类的朋友准备骂骂咧咧退出群聊了哈。少安勿躁。

抽象基类

什么是抽象基类?就是把n个类,抽出共同特征,然后组成一个基类。这些共同特征,可以是类属性,也可以是类方法。

比方说猫类、狗类和鸟类,它们就可以抽象出:它们都是动物、它们都会叫、都会吃喝拉沙睡···把这些共同点有机组合成一个类,就是抽象基类,就叫ABC类吧。

然后呢,猫类、狗类、鸟类都继承于ABC类。

这样有什么好处呢?有的,统筹兼顾。怎么个统筹兼顾法,别急往下看。

回到上面那个超市促销活动,那个活动有什么共通点?或者说,那些促销方式有什么共同点?有的,最后都要结账的,不能拎着东西你就跑吧。

超市促销活动的UML策略模式类图


策略模式实现

刚刚说不了解抽象基类的朋友先别急,如果实在不了解抽象基类,可以看一下这里的代码。

如何判断一个类是否为抽象基类呢?就看它有没有纯虚函数。

而且,如果是抽象基类的话,是不能引用类对象,万年单身狗啊。

#include<iostream>

using namespace std;

//抽象基类
class cashbase
{
public:
	virtual double accept_cash(double money) = 0;
};

//各个子类
class cashnormal: public cashbase
{
public:
	double accept_cash(double money) { return money; }	//原价返回
};

class cashrebate: public cashbase
{
private:
	double rebate;
public:
	cashrebate(double rebate) { this->rebate = rebate; }
	double accept_cash(double money) { return money * this->rebate; }
};

class cashreturn: public cashbase
{
private:
	double moneycondition = 0.0;
	double moneyreturn = 0.0;
public:
	cashreturn(double moneycondition, double moneyreturn)
	{
		this->moneycondition = moneycondition;
		this->moneyreturn = moneyreturn;
	}

	double accept_cash(double money)
	{
		if (money >= this->moneycondition)
			return (money - this->moneyreturn);
		else
			return money;
	}
};

//早期模式工厂
//class cashcontex
//{
//private:
//	cashbase *cb;	//这不是类引用对象
//public:
//	cashcontex(cashbase* cb) { this->cb = cb; }//将收费策略作为参数传入
//	double getresult(double money) { return cb->accept_cash(money); }
//
//};
//由于会绕回工厂模式的老路,故取消这种做法

class cashcontex
{
private:
	cashbase* cb = NULL;//这是指针对象
public:
	cashcontex(int type, double rebate, double moneycondition, double moneyreturn)
	{
		if (type == 0)
		{
			cashnormal* cn = new cashnormal();
			cb = cn;
		}
		else if (type == 1)
		{
			cashrebate* cr = new cashrebate(rebate);
			cb = cr;
		}
		else if (type == 2)
		{
			cashreturn* crt = new cashreturn(moneycondition, moneyreturn);
			cb = crt;
		}
	}

	double getresult(double money){return cb->accept_cash(money);}
};


int main()
{
	cashcontex* cc = new cashcontex(1, 0.6, 0, 0);

	double ret = cc->getresult(300.0);

	cout << ret << endl;
	return 0;
}

上面这套代码呢,其实是策略模式和简单工厂的结合。

回顾策略模式

策略模式通过 定义一系列算法的方法,减少各种算法类与使用算法类之间的耦合(上面那个main,只能姐醋到一个cashcontex类)。

策略模式简化了单元测试,因为每个算法都有自己的类,可以通过自己的借口单独测试。就算某个算法出问题,也不会影响到其他的算法。