一,概念
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
二,策略模式的组成
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就可以了
相对与策略模式的提升为:客户端需要承担的判断更少了,更简洁了