设计模式之策略模式学习

策略模式:它定义了算法家族,分别封装起来,让他么之间可以互相替换。此模式让算法的变化,不会影响使用这些算法的客户。

在引出策略模式时,讨论了超市收银系统。可以将各种收费项目抽象成几种操作,比如正常收费、打折、返现、返积分。。。对打折来说,之所以可以这样进行抽象因为各种折扣之间存在着相互的联系,故将其抽象为一种。返现、返积分也类似。

算法本身是一种策略,这些算法可能随时被替换,这就是变化点,而封装变化点是面向对象一种很重要的思维方式。

策略模式是定义了一系列算法的方法,从概念上来看所有这些算法完成相同的工作,只是实现不同。它可以以相同的方式调用所有的算法,减少了各种算法类与使用它的算法类之间的耦合。

看代码:

//收费对象虚基类。

class SuperCashier
{
public:
	double price;
	int num;
public:
	SuperCashier(double price,int num)
	{
		this->price=price;
		this->num=num;

	}
	virtual double getTotalMoney()=0; 

} ;

//正常收费

class Normal:public SuperCashier
{
public:

	double discount;
public:
	Normal(double price,int num)
		:SuperCashier(price,num)
	{

	}
	virtual double getTotalMoney()
	{
		return price*num;
	}

} ;

//打折 
class Discount:public SuperCashier
{
public:

	double discount;
public:
	Discount(double price,int num,double discount)
		:SuperCashier(price,num)
	{
		this->discount=discount;
	}
	virtual double getTotalMoney()
	{
		return price*num*discount;
	}

} ;


//返点 
class ReturnPoint :public SuperCashier
{
public:
	double conditionMoney;
	double point;
public :
	ReturnPoint(double price,double num,double cm,double rp)
		:SuperCashier(price,num),conditionMoney(cm),point(rp)
	{

	} 
	virtual double getTotalMoney()
	{
		double total=price*num;
		if(total>=conditionMoney)
		{
			double n=total/conditionMoney;
			return point*n;

		} 
		return 0;
	} 

};

//返现金
class ReturnMoney:public SuperCashier
{
public:
	double conditionMoney;
	double returnNum;
public:
	ReturnMoney(double price,double num,double cm,double returnNum)
		:SuperCashier(price,num),conditionMoney(cm)
	{
		this->returnNum=returnNum;
	}
	virtual double getTotalMoney()
	{
		double total=num*price;
		if(total>=conditionMoney)
		{
			double n=total/conditionMoney;
			return total-n*returnNum;
		}
	}
} ;


/************************************************************************/
/* 策略模式。                                                             */
/***********************************************************************
class CashContext
{
public:
	SuperCashier*sc;
public:
	CashContext(SuperCashier*sc)
	{
		this->sc=sc;
	}
	double getResult()
	{
		return sc->getTotalMoney();
	}


};
//在客户端进行判断。
int main(int argc,char**argv)
{
	double price;
	double num;
	CashContext *cc; 
	while(1)
	{
		cout<<"1..正常收费。2..打折。3..返点 4..返利"<>ch;getchar();
		switch(ch)
		{
		case 1:
			{
				cin>>price>>num;
				cc=new CashContext(new Normal(price,num));


			}
			break;
		case 2:
			{
				double discount;
				cin>>price>>num>>discount;
				cc=new CashContext(new Discount(price,num,discount));
			}
			break;
		case 3:
			{
				double conditionMoney;
				double returnPoint;
				cin>>price>>num>>conditionMoney>>returnPoint;
				cc=new CashContext(new ReturnPoint(price,num,conditionMoney,returnPoint));
			}
			break;
		case 4:
			{
				double conditionMoney;
				double returnMoney;
				cin>>price>>num>>conditionMoney>>returnMoney;
		           cc=new CashContext(new ReturnMoney(price,num,conditionMoney,returnMoney));
			}
			break;
		default:
			break;
		} 
		cout<getResult()<


/************************************************************************/
/* 策略模式与简单工厂模式结合,即将在main中的switch循环移到CashContext类中       */
/************************************************************************/
class CashContext
{
public:
	int type;
	double price;
	double num;
	double discount;
	double conditionMoney;
	double ret;
	SuperCashier *sc;
public:
	CashContext(int t,double price,int num,double discount)
		:type(t)
	{
		this->price=price;
		this->num=num;
		this->discount=discount;
		
		sc=NULL;
	}
	CashContext(int t,double price,int num)
		:type(t)
	{
		this->price=price;
		this->num=num;
		sc=NULL;
	}
	CashContext(int t,double price,int num,double conditionMoney,double ret)
		:type(t)
	{
		this->price=price;
		this->num=num;
		this->conditionMoney=conditionMoney;
		this->ret=ret;
		sc=NULL;
	}
	double getResult()
	{
		
		switch(type)
		{
		case 1://正常收费
			{
				sc=new Normal(price,num);
			}
			break;
		case 2://打折
			{
				sc=new Discount(price,num,discount);
			}
			break;
		case 3://返点
			{
				sc=new ReturnPoint(price,num,conditionMoney,ret);
			}
			break;
		case 4://返现
			{
				sc=new ReturnPoint(price,num,conditionMoney,ret);
			}
			break;
		default:
			break;
		}
		return sc->getTotalMoney();

	}
};
int main(int argc,char**argv)
{
	CashContext *cc;
	double price,num,discount,conditionMoney,ret;

	cin>>price>>num;
	cc=new CashContext(1,price,num);
	cout<getResult()<>price>>num>>discount;
	cc=new CashContext(2,price,num,discount);
	cout<getResult()<>price>>num>>conditionMoney>>ret;
	cc=new CashContext(3,price,num,conditionMoney,ret);
	cout<getResult()<>price>>num>>conditionMoney>>ret;
	cc=new CashContext(4,price,num,conditionMoney,ret);
	cout<getResult()<
 
  

此处觉得有不妥,一旦超市推出另外一些活动,CashContext类中用于switch判断的代码就要修改,程序需要重新编译。这在实际应用中是不可能的。第二章的最后提了一下使用映射可以解决这个问题。但不知映射为何物,拭目以待吧

注:此处实现的收费对象类,比书上的多实现了返点类。关于此类不知应该将其归为哪一部分,暂将其放入收费对象类中。但觉得不应该与收费对象类放在一起,应该有另外一个类处理返点。毕竟积分信息的管理对于大型超市来说也是很重要的一部分。

你可能感兴趣的:(设计模式之策略模式学习)