1.问题描述:
有一个人的商场开业,希望能在短期内提升顾客数量,他打算采用多用促销方式,有价格折扣、满300返100,然后过一段时间后再把收银方式调整正常。但是如果之后又遇到节假日,他又会开启一些新的促销方式。
上面这个例子该如何去管理这个商店的收银方式呢。
2.思路方向
考虑到代码的封装和多态性,我们需要采用面向对象的方式来解决这一个问题。我们可以先定义一个收银类这一个抽象类并给出一个收银的抽象方法,然后根据不同的促销方式分别继承收银类并实现收银方法。这样我们就有了多个促销的功能(类)了,接下来就是想办法去实例化和使用它们。
如果参考简单工厂模式的话,我们应该再写出一个工厂类,但是由于这个例子中会经常出现促销活动的变化。每次变化我们不仅需要去修改原来的促销方式类或者新添促销方式类,还要去修改工厂里的代码,工作量比较的大。所以我们会去采用另一个模式——策略模式。
//收银类
abstract class CrashSuper
{
public abstract double AcceptCrash(double money);
}
//正常情况
class CrashNormal : CrashSuper
{
public override double AcceptCrash(double money)
{
return money;
}
}
//打折促销
class CrashRebate : CrashSuper
{
private double moneyRebate = 1.0f;
public CrashRebate(double rebate )
{
if (rebate > 0 && rebate <= 1)
moneyRebate = rebate;
}
public override double AcceptCrash(double money)
{
return money*moneyRebate;
}
}
//满xx返xx促销方式
class CrashReturn : CrashSuper
{
private double moneyCondition = 0;
private double moneyReturn = 0;
public CrashReturn(double mCondition, double mReturn)
{
if (mCondition >= 0 && mReturn >= 0)
{
moneyCondition = mCondition;
moneyReturn = mReturn;
}
}
public override double AcceptCrash(double money)
{
if (moneyCondition <= money && moneyReturn <= money)
{
money -= Math.Floor(money / moneyCondition) * moneyReturn;
}
return money;
}
}
3.策略模式
策略模式是需要专门去新写一个crashContext类,crashContext类的构造方法会来接收不同促销方式的实例化对象,并在crashContext中去调用每种促销模式的费用计算方法。
具体哪一种促销方法的选择不由crashContext类来选择,它只接收一个促销方法的实例并调用它。在这样的模式下,以后无论是原有促销方式有了修改,还是出现了新的促销方式,我们都可以不用来修改crashContext中的代码。
每一种促销方式的实例化是在crashContext外实现的,可能在客户端中实现好,根据所需的促销方式传递给crashContext。
class CrashContext
{
private CrashSuper cs;
public CrashContext(CrashSuper cSuper)
{
cs = cSuper;
}
public double GetResult(double money)
{
return cs.AcceptCrash(money);
}
}
4.UML图
5.总结
策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
策略模式和简单工厂模式的区别:策略模式是将多种功能分离开来,并将它们提供出来,具体选择哪一个功能去完成要求得自己去实现;简单工厂模式也同样将这些功能给分离开了,但是选择什么功能去完成要求是由工厂来完成的,外部只需要告诉工厂需要完成的要求就好,工厂会选出并返回相应功能的实例。
优点:1、算法可以自由切换。2、避免使用多重条件判断。3、扩展性良好。4、每个功能都有自己的类,可以通过自己的接口方便单元测试。
缺点:1、策略类会增多。2、所有策略类都需要对外暴露。
使用场景:1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。2、一个系统需要动态地在几种算法中选择一种。3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。