商场促销 --- 策略模式

一,概念

        策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

二,策略模式的组成

   1)抽象策略角色: 策略类,通常由一个接口或者抽象类实现。
   2)具体策略角色:包装了相关的算法和行为。

   3)环境角色:持有一个策略类的引用,最终给客户端调用。

三,补充C++知识

类对象的构造顺序是这样的:
  1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员
  2.进入构造函数后在构造函数中执行一般计算
       1)类里面的任何成员变量在定义时是不能初始化的。
       2)一般的数据成员可以在构造函数中初始化。
       3)const数据成员必须在构造函数的初始化列表中初始化。
       4)static要在类的定义外面初始化。   
       5)数组成员是不能在初始化列表里初始化的。
       6)不能给数组指定明显的初始化。  
这6条一起,说明了一个问题:C++里面是不能定义常量数组的!因为3和5的矛盾。这个事情似乎说不过去啊?没有办法,我只好转而求助于静态数据成员。
到此,我的问题解决。但是我还想趁机复习一下C++类的初始化:
  1.初始化列表:CSomeClass::CSomeClass() : x(0), y(1){}
  2.类外初始化:int CSomeClass::myVar=3;
  3.const常量定义必须初始化,C++类里面使用初始化列表;
  4.C++类不能定义常量数组。

在C++类中,必须做如下事情:

1.必须对任何const或引用类型成员以及没有默认构造函数的 类 类型 的任何成员 显示地使用初始化列表进行初始化

2.类成员在定义时是不能被初始化的

3.类的成员初始化顺序与成员变量在构造函数中的位置选后顺序无关,只与成员变量在类中定义的先后顺序有关

C++默认继承方式为private

C++ new 生成的对象为指针,所以new 前面的对象要声明为指针类型

四,实例

        计算器简单工厂模式的精简实现

#include <iostream>  
using namespace std;  
  
class COperation//基类  
{  
public:
	COperation(){}

	void setNumberA(int value)
	{
		NumberA=value;
	}

	int getNumberA()
	{
		return NumberA;
	}

	void setNumberB(int value)
	{
		NumberB=value;
	}

	int getNumberB()
	{
		return NumberB;
	}

    virtual double GetResult()  
    {  
        double Result=0;  
        return Result;  
    }  
private:
	int NumberA;  
    int NumberB; 
};  
  
class AddOperation : public COperation//加法  
{  
public:  
    virtual double GetResult()  
    {  
        return getNumberA()+getNumberB();  
    }  
};  
  
class SubOperation : public COperation//减法  
{  
public:  
    virtual double GetResult()  
    {  
        return getNumberA()-getNumberB();  
    }  
};  
  
  
class CCalculatorFactory//工厂类  
{  
      
public:  
    COperation* Create(char cOperator)
	{
		switch (cOperator)  
		{  
			case '+':  
				oper=new AddOperation();  
				 break;  
			case '-':  
				oper=new SubOperation();  
				break;  
			default:  
				oper=new AddOperation();  
				break;  
		}  
		return oper; 
	}
private:
	COperation *oper; 
};  
  
int main()  
{  
    int a,b;  
	cout<<"输入数字A"<<endl;
	cin>>a;
	cout<<"输入数字B"<<endl;
    cin>>b;
	
	cout<<"请选择运算符符号(+、-、*、/)"<<endl;
	char operate;
	cin>>operate;
      
	CCalculatorFactory Calculator;
   
    COperation * op = Calculator.Create(operate);
    op->setNumberA(a);  
    op->setNumberB(b);  
    cout<<op->GetResult()<<endl;  
    return 0;  
}



将简单工厂模式优化为策略模式后的代码如下:

#include <iostream>
using namespace std; 

//策略基类
class COperation
{
public:	
	COperation(){}
	COperation(int numA,int numB):NumberA(numA),NumberB(numB){}
	void setNumberA(int value)  
    {  
        NumberA=value;  
    }  
  
    int getNumberA()  
    {  
        return NumberA;  
    }  
  
    void setNumberB(int value)  
    {  
        NumberB=value;  
    }  
  
    int getNumberB()  
    {  
        return NumberB;  
    }  
  
    virtual double GetResult()    
    {    
        double Result=0;    
        return Result;    
    }    
private:  
    int NumberA;    
    int NumberB;   
};

//
//策略具体类-加法类
class AddOperation : public COperation
{
public:
	AddOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()+getNumberB();
	}
};

//策略具体类-减法类
class SubOperation : public COperation
{
public:
	SubOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()-getNumberB();
	}
};

//策略具体类-除法类
class DivOperation : public COperation
{
public:
	DivOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		if(getNumberB()==0)
			throw new exception("除数为0");
		return getNumberA()/getNumberB();
	}
};

//策略具体类-乘法类类
class MulOperation : public COperation
{
public:
	MulOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()*getNumberB();
	}
};
///


class Context//策略类 
{
private:
	COperation* op;
public:
    Context(COperation* temp)//参数为策略基类(传递的时候被初始化为子类) 
	{
        op=temp;
	}
	double GetResult()
	{
		return op->GetResult();
	}
};

//客户端
int main()
{
	int a,b;
    char c;
	cout<<"输入操作数A和B"<<endl;
	cin>>a>>b;
    cout<<"请输入运算符:";
    cin>>c;

	Context *context;
    switch(c)
    {
       case '+':
	        context=new Context(new AddOperation(a,b));
			break;
	   case '-':
		    context=new Context(new SubOperation(a,b));
            break;
		case '*':
		    context=new Context(new MulOperation(a,b));
            break;
		case '/':
		    context=new Context(new DivOperation(a,b));
            break;
       default:
		   Context *context=new Context(new AddOperation(a,b));
    }
	cout<<context->GetResult()<<endl; 

	return 0;
}

这里将策略(操作符)封装成一个Context类,通过传递操作符子对象来返回相应子对象下操作结果。



菜鸟实现工厂模式和策略模式

 客户端只需访问Context类,而不用知道其它任何类信息,实现了低耦合。在上例基础上,修改下面内容

#include <iostream>
using namespace std; 

//策略基类
class COperation
{
public:	
	COperation():NumberA(0),NumberB(0){}
	COperation(int numA,int numB):NumberA(numA),NumberB(numB){}
	void setNumberA(int value)  
    {  
        NumberA=value;  
    }  
  
    int getNumberA()  
    {  
        return NumberA;  
    }  
  
    void setNumberB(int value)  
    {  
        NumberB=value;  
    }  
  
    int getNumberB()  
    {  
        return NumberB;  
    }  
  
    virtual double GetResult()    
    {    
        double Result=0;    
        return Result;    
    }    
private:  
    int NumberA;    
    int NumberB;   
};

//
//策略具体类-加法类
class AddOperation : public COperation
{
public:
	AddOperation():COperation(){}
	AddOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()+getNumberB();
	}
};

//策略具体类-减法类
class SubOperation : public COperation
{
public:
	SubOperation():COperation(){}
	SubOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()-getNumberB();
	}
};

//策略具体类-除法类
class DivOperation : public COperation
{
public:
	DivOperation():COperation(){}
	DivOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		if(getNumberB()==0)
			throw new exception("出数为0");
		return getNumberA()/getNumberB();
	}
};

//策略具体类-乘法类类
class MulOperation : public COperation
{
public:
	MulOperation():COperation(){}
	MulOperation(int a,int b):COperation(a,b){}
	virtual double GetResult()
	{
		return getNumberA()*getNumberB();
	}
};
///


class Context  
{  
private:  
    COperation* op;  
public:  
    Context(int NumA,int NumB,char cType)  
    {  
        switch (cType)  
        {  
        case '+':  
            op=new AddOperation(NumA,NumB);  
            break;  
		case '-':
			op=new 	SubOperation(NumA,NumB);
			break;
		case '*':
			op=new 	MulOperation(NumA,NumB);
			break;
		case '/':
			op=new 	DivOperation(NumA,NumB);
			break;
        default:  
            op=new AddOperation();  
            break;  
        }  
    }  
    double GetResult()  
    {  
        return op->GetResult();  
    }  
};  
//客户端  
int main()  
{  
	int a,b;
    char c;
	cout<<"输入操作数A和B"<<endl;
	cin>>a>>b;
    cout<<"请输入运算符:"<<endl;
    cin>>c;
    Context *test=new Context(a,b,c);  
    cout<<test->GetResult()<<endl;  
    return 0;  
}  


五,商场促销例子

        这里想说的是,abstract 关键字是微软为C#定义的,抽象类关键字。C++中没有抽象类,如果想成为抽象类在类中定义纯虚函数就可以了。只要拥有纯虚函数的类就是抽象类,由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

         商场促销的简单工厂实现:

#include <iostream>
#include <String>  
  
using namespace std;  
  
class CashSuper //现金收费抽象类  
{  
public:  
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! (不能只定义,而不实现)  
    {  
          return 0;
    }  
};  
  
class CashNormal : public CashSuper //收费子类,正常收费  
{  
public:  
     double acceptCash(double money)  
     {  
         return money;  
     }  
      
};  
  
class CashRebate : public CashSuper //打折收费子类  
{  
private:  
    double moneyRebate;//不允许初始化  
public:  
    CashRebate(double moneyRebate)  
    {  
        this->moneyRebate=moneyRebate;  
    }  
    double acceptCash(double money)  
    {  
         return money*moneyRebate;  
    }  
};  
  
class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)  
{  
private:  
    double moneyCondition ;//返利购买额度  
    double moneyReturn ;//返利多少  
public:  
    CashReturn(double moneyCondition,double moneyReturn)  
    {  
        this->moneyCondition=moneyCondition;  
        this->moneyReturn=moneyReturn;  
    }  
    double acceptCash(double money)  
    {  
        double result = money;  
        if(money >= moneyCondition )  
            result = money-(money/moneyCondition)*moneyReturn;  
        return result;  
          
    }  
};  
  
class CashFactory  
{  
public:  
    static CashSuper* creatCashAccept(string type)//根据子类type来生成相应收费子类  
    {  
        CashSuper *cs;  
        if(type == "CashNormal")  
            cs=new CashNormal();  
        else if(type == "CashRebate")  
            cs=new CashRebate(0.8);  
        else if(type == "CashReturn")  
            cs=new CashReturn(300,100);  
          
        return cs;  
    }  
};  
  
int main(int argc, char** argv) 
{  
    CashSuper *csuper = CashFactory::creatCashAccept("CashRebate");  
    double result=csuper->acceptCash(500);//500打八折,应该输出 400  
    cout<<"CashRebate 500 is:"<<result<<endl;  
    return 0;  
}  
策略模式:定义了算法家族,分别封装起来,让它们之间可以相互替换,算法的变化不会影响使用算法的客户。
主要升级就是,将算法封装到Context中,然后通过传递对象生成相应子类对象,然后得到结果。

#include <iostream>
#include <String>

using namespace std;

class CashSuper //现金收费抽象类
{
public:
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! 
    {
        return 0;
    }
};

class CashNormal : public CashSuper //收费子类,正常收费
{
public:
     double acceptCash(double money)
     {
         return money;
     }
    
};

class CashRebate : public CashSuper //打折收费子类
{
private:
    double moneyRebate;//不允许初始化
public:
    CashRebate(double moneyRebate)
    {
        this->moneyRebate=moneyRebate;
    }
    double acceptCash(double money)
    {
         return money*moneyRebate;
    }
};

class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)
{
private:
    double moneyCondition ;//返利购买额度
    double moneyReturn ;//返利多少
public:
    CashReturn(double moneyCondition,double moneyReturn)
    {
        this->moneyCondition=moneyCondition;
        this->moneyReturn=moneyReturn;
    }
    double acceptCash(double money)
    {
        double result = money;
        if(money >= moneyCondition )
            result = money-(money/moneyCondition)*moneyReturn;
        return result;
        
    }
};

class CashContext
{
private:
    CashSuper *cs;
public:
    CashContext(CashSuper *csuper)
    {
        this->cs=csuper;
    }
    double GetResult(double money)
    {
        return cs->acceptCash(money);
    }
};

int main(int argc, char** argv) {

    //CashSuper *csuper = CashFactory::creatCashAccept("CashRebate");
    //double result=csuper->acceptCash(500);//500打八折,应该输出 400
    
    
     CashContext *cs;
     string type="CashRebate";
     
     if(type=="CashNormal")
            cs = new CashContext(new CashNormal());
     else if(type == "CashRebate")
            cs = new CashContext(new CashRebate(0.8));
     else if(type == "CashReturn")
            cs = new CashContext(new CashReturn(300,100));
            
    cout<<"CashRebate 500 is"<<cs->GetResult(500)<<endl;
    return 0;
}




这样仍然存在缺点:就是让客户端来判断生成哪个子类。

改进策略是,让策略模式和工厂模式结合

#include <iostream>
#include <String>

using namespace std;

class CashSuper //现金收费抽象类
{
public:
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! 
    {
        return 0;
    }
};

class CashNormal : public CashSuper //收费子类,正常收费
{
public:
     double acceptCash(double money)
     {
         return money;
     }
    
};

class CashRebate : public CashSuper //打折收费子类
{
private:
    double moneyRebate;//不允许初始化
public:
    CashRebate(double moneyRebate)
    {
        this->moneyRebate=moneyRebate;
    }
    double acceptCash(double money)
    {
         return money*moneyRebate;
    }
};

class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)
{
private:
    double moneyCondition ;//返利购买额度
    double moneyReturn ;//返利多少
public:
    CashReturn(double moneyCondition,double moneyReturn)
    {
        this->moneyCondition=moneyCondition;
        this->moneyReturn=moneyReturn;
    }
    double acceptCash(double money)
    {
        double result = money;
        if(money >= moneyCondition )
            result = money-(money/moneyCondition)*moneyReturn;
        return result;
        
    }
};

class CashContext
{
private:
    CashSuper *cs;
public:
    CashContext(string type)
    {
        //this->cs=csuper;
	   	 if(type=="CashNormal")
                cs = new CashNormal();
		 else if(type == "CashRebate")
				cs = new CashRebate(0.8);
		 else if(type == "CashReturn")
				cs = new CashReturn(300,100);
    }
    double GetResult(double money)
    {
        return cs->acceptCash(money);
    }
};

int main(int argc, char** argv) {

    //CashSuper *csuper = CashFactory::creatCashAccept("CashRebate");
    //double result=csuper->acceptCash(500);//500打八折,应该输出 400
    
    
     CashContext *cs;
     string type="CashRebate";

	 cs = new CashContext(type);
       
    cout<<"CashRebate 500 is"<<cs->GetResult(500)<<endl;
    return 0;
}



这样客户端只需要更改金额和打折手段就可以了。相对简单工厂的提升为:简单工厂需要让客户调用两个类SuperCash和CashFactory。而结合之后仅仅需要调用CashContext就可以了

相对与策略模式的提升为:客户端需要承担的判断更少了,更简洁了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值