商场促销 --- 策略模式

来源:互联网 发布:拳皇开发源码 编辑:程序博客网 时间:2024/04/27 16:07

一,概念

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

二,策略模式的组成

   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就可以了

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


原创粉丝点击