大话设计模式2-策略模式(商场促销)

本文介绍了商场促销的策略模式实现,从简单工厂到策略模式的转变,以及如何结合两者以减少接口复杂性。通过封装不同促销策略,如正常收费、打折和满减,实现了算法的独立性和可扩展性。在main函数中,策略模式使得客户端只需关注选择的促销策略,而具体的计算逻辑则由策略对象处理。
摘要由CSDN通过智能技术生成

1.需求:商场促销

商场有不同的促销情况,可以打折、满减以及不促销

2.简单工厂实现

简单工厂实现可以①设计一个收费抽象类,交给子类去重写

#pragma once
class cashSuper {
public :
	virtual double acceptCash(double money)
	{
		return money;
	}
};

②再定义正常收费、满减、打折三个子类。
正常收费

#pragma once
#include"cashSuper.h"
class cashNomal :public cashSuper {
public:
	double acceptCash(double money)
	{
		return money;
	}
};

打折

#pragma once
#include"cashSuper.h"
class cashRebate :public cashSuper {
public:
	cashRebate(double bate = 1):rebate(bate){}
	double acceptCash(double money){
		return money*rebate;
	}
private:
	double rebate;
};

满减
构造时需要两个参数分别是满减条件以及满减金额

#pragma once
#include"cashSuper.h"
class cashReturn :public cashSuper {
private:
	double moneycond;
	double moneyret;
public:
	cashReturn(double cond,double ret):moneycond(cond),moneyret(ret){}
	double acceptCash(double money)
	{
		double res = money;
		if (money > moneycond)
			res = money - int((money / moneycond))* moneyret;
		return res;
	}
};

③之后是工厂类,用来实例化合适的对象

#pragma once
#include"cashNormal.h"
#include"cashRebate.h"
#include"cashReturn.h"
#include"cashSuper.h"
using namespace std;
enum typeset{nomal,rebate,ret};
class moneyFactory {
public:
	cashSuper* createCash(typeset type) {
		cashSuper* cs = nullptr;
		switch (type)
		{
			case nomal:
				cs = new cashNomal();
				break;
			case rebate:
				cs = new cashRebate(0.8);
				break;
			case ret:
				cs = new cashReturn(300,100);
				break;
		}
		return cs;
	}
};

④main函数

#include"moneyFactory.h"
#include<iostream>

int main()
{
	double res;
	cashSuper* su;
	moneyFactory factory;

	su = factory.createCash(nomal);
	res = su->acceptCash(600);
	cout << res << endl;

	su = factory.createCash(rebate);
	res = su->acceptCash(600);
	cout << res << endl;

	su = factory.createCash(ret);
	res = su->acceptCash(600);
	cout << res << endl;

	return 0;
}

输入为600,在正常、打八折、满300减100情况下输出:
在这里插入图片描述
在这里插入图片描述

3.策略模式

策略模式定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。

说白了就是封装各个促销方法,定义一个支持所有算法的接口cashSuper这一步我们已经完成了,其次再通过一个cashContext类维护cashSuper指针。
cashContext两个作用:构造cashSuper指针,根据具体的方法调用cashSuper类算法完成多态,也就是说提供了接口。让cashSuper子类中的方法与客户进行隔离,客户只知道cashContext

#pragma once
#include"cashSuper.h"
class cashContext {
public:
	cashContext(cashSuper *super): su(super){}
	double getRes(double money) {
		return su->acceptCash(money);		 
	}
private:
	cashSuper* su;
};

正常收费、满减、打折三个子类不变。
正常收费

#pragma once
#include"cashSuper.h"
class cashNomal :public cashSuper {
public:
	double acceptCash(double money)
	{
		return money;
	}
};

打折

#pragma once
#include"cashSuper.h"
class cashRebate :public cashSuper {
public:
	cashRebate(double bate = 1):rebate(bate){}
	double acceptCash(double money){
		return money*rebate;
	}
private:
	double rebate;
};

满减
构造时需要两个参数分别是满减条件以及满减金额

#pragma once
#include"cashSuper.h"
class cashReturn :public cashSuper {
private:
	double moneycond;
	double moneyret;
public:
	cashReturn(double cond,double ret):moneycond(cond),moneyret(ret){}
	double acceptCash(double money)
	{
		double res = money;
		if (money > moneycond)
			res = money - int((money / moneycond))* moneyret;
		return res;
	}
};
#pragma once
class cashSuper {
public :
	virtual double acceptCash(double money)
	{
		return money;
	}
};

main函数实现

#include"cashContext.h"
#include"cashNormal.h"
#include"cashRebate.h"
#include"cashReturn.h"
#include"cashSuper.h"
#include<iostream>
using namespace std;
enum typeset { nomal, rebate, ret };
int main()
{
	typeset type = ret;
	cashContext* cc = nullptr;
	switch (type)
	{
		case nomal:
			cc = new cashContext(new cashNomal());
			break;
		case rebate:
			cc = new cashContext(new cashRebate(0.8));
			break;
		case ret:
			cc = new cashContext(new cashReturn(300, 100));
			break;
	}
	double res = cc->getRes(600);
	cout << res;

	return 0;
}

在这里插入图片描述

4.策略模式与简单工厂的结合

我们先分析工厂模式与策略模式的缺点。
如下图工厂模式中,我们需要工厂类和现金消费类两方协助才能够完成促销计算,增加了接口,维护较复杂。

在这里插入图片描述
而策略模式虽然只需要一个上下文接口,但是在main函数也就是客户端中判断使用哪个算法,实现上也不好。我们想把判断过程封装起来,这时我们需要工厂来封装,接口过多的问题我们需要策略模式解决,所以需要结合两种模式。
由于我们客户希望只知道cashContext,所以要把工厂类搬到cashContext中,或者说由cashContext来实例合适的对象

以前的工厂类如下:

#include"cashReturn.h"
#include"cashSuper.h"
using namespace std;
enum typeset{nomal,rebate,ret};
class moneyFactory {
public:
	cashSuper* createCash(typeset type) {
		cashSuper* cs = nullptr;
		switch (type)
		{
			case nomal:
				cs = new cashNomal();
				break;
			case rebate:
				cs = new cashRebate(0.8);
				break;
			case ret:
				cs = new cashReturn(300,100);
				break;
		}
		return cs;
	}
};

以前的cashContext类如下

#pragma once
#include"cashSuper.h"
class cashContext {
public:
	cashContext(cashSuper *super): su(super){}
	double getRes(double money) {
		return su->acceptCash(money);		 
	}
private:
	cashSuper* su;
};

合并,cashContext依旧维护抽象计算cashSuper的指针,此外还负责实例化具体策略。

#pragma once
#include"cashSuper.h"
#include"cashNormal.h"
#include"cashRebate.h"
#include"cashReturn.h"

enum typeset { nomal, rebate, ret };
class cashContext {
public:
	cashContext(typeset type)
	{
		switch (type)
		{
			case nomal:
				cs = new cashNomal();
				break;
			case rebate:
				cs = new cashRebate(0.8);
				break;
			case ret:
				cs = new cashReturn(300, 100);
				break;
		}
	}
	double getRes(double money) 
	{
		return cs->acceptCash(money);		 
	}
private:
	cashSuper* cs;
};

其余cashSuper类和三个子类不变
main函数如下

#include"cashContext.h"
#include<iostream>
using namespace std;

int main()
{
	typeset s = ret;//满减
	cashContext* cc = new cashContext(s);	
	double res = cc->getRes(600);
	cout << res;

	return 0;
}

可以看出客户只认识cashContext,通过传入的策略多态实现促销计算。

5.反思

策略模式可以将一系列算法封装起来,以相同的方式调用所有算法,减少了接口、每个算法也都有自己的类,可以单独进行调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值