策略模式
策略模式:定义一组同类型的算法,将这些算法分别在不同的类中封装起来,不同的算法可以根据不同的情况进行替换调用以满足需求。
策略模式跟简单工厂模式很相似
策略模式:context类,策略抽象类,策略类
工厂模式:工厂类,产品抽象类,产品类
平时生活中遇到最多的策略是商场打折:满减,打折以及正常付账
以下是工厂模式和策略模式类图对照:
抽象类和具体类:
class AbstractAlgorithm
{
public:
double AcceptCash(double money)
{
return money;
}
};
class DiscountAlgorithm :public AbstractAlgorithm
{
public:
DiscountAlgorithm(double discount)
:mDiscount(discount)
{
};
double AcceptCash(double money)
{
return money*mDiscount;
}
private:
double mDiscount;
};
class DeductAlgorithm :public AbstractAlgorithm
{
public:
DeductAlgorithm(double atleast,double deduct)
:mAtLeast(atleast),
mDeduct(deduct)
{
};
double AcceptCash(double money)
{
if (mAtLeast > money)
return money;
return money - mDeduct;
}
private:
double mAtLeast;
double mDeduct;
};
工厂模式部分代码:
struct AlgorithmType
{
enum
{
Normal = 0,
Discount,
Deduct,
};
};
class Factory
{
public:
AbstractAlgorithm* CreateAlgorithm(int type)
{
AbstractAlgorithm* AA = NULL;
switch (type)
{
case AlgorithmType::Normal:
AA = new AbstractAlgorithm();
break;
case AlgorithmType::Discount://8折
AA = new DiscountAlgorithm(0.8);
break;
case AlgorithmType::Deduct://满300减100
AA = new DeductAlgorithm(300, 100);
default:
break;
}
return AA;
}
};
int main()
{
Factory* AlgorithmFactory = new Factory();
//8折
AbstractAlgorithm* Discout8 = AlgorithmFactory->CreateAlgorithm(AlgorithmType::Discount);
cout << "100元打8折应付:" << Discout8->AcceptCash(8) << endl;
}
策略模式部分代码:
class Context
{
public:
void SetAlgorithm(AbstractAlgorithm algoruthm)
{
mAlgorithm = algoruthm;
}
double GetResult(double money)
{
return mAlgorithm.AcceptCash(money);
}
private:
AbstractAlgorithm mAlgorithm;
};
int main()
{
AbstractAlgorithm* D8 = new DiscountAlgorithm(0.8);
Context* AlgorithmContext = new Context();
AlgorithmContext->SetAlgorithm(*D8);
cout << "100元打8折应付:" << AlgorithmContext->GetResult(100) << endl;
}
在上面两个模式中,main()可代表客户端,最终得到的结果是一样的。但是看起来使用策略模式在开闭原则(对扩展开发,对修改关闭)和单一原则(一个类只有1个发生变化的原因)上有更好的表现。同时解决了过多使用if-esle的问题,提高代码的可拓展性,可维护性和可读性。最后,单元测试时,只需要测试单独的策略类就好,不影响其他类。
当然,策略模式也有比较明显的缺点:
1.客户端必须清楚所有的策略类,才能清楚要使用哪个策略。
2.需求增加时,判断逻辑在客户端处理。
适用场景:
1.程序运行时,需要动态地使用不同策略去实现需求。