首页 > 代码库 > 策略模式

策略模式

引入问题:要实现一个商场收费软件,根据单价,数量来向客户收费,其中收费方式可以有多种(变化多)。

方法一:简单工厂模式实现

一个CashSuper类统一接口,多个具体的计算类继承于CashSuper类,一个工厂方法CashFactory创建具体实现类。

//现金收费抽象类abstract class CashSuper{    public abstract double acceptCash(double money);}//正常收费class CashNormal : CashSuper{    public override double acceptCash(double money)    {        return money;    }}//打折收费类class CashRebate:CashSuper{    private double moneyRebate = 1d;    public CashRebate(String moneyRebate)    {        this.moneyRebate = double.Parse(moneyRebate);    }    public override double acceptCash(double money)    {        return moneyRebate*money;    }}//返利收费class CashReturn:CashSuper{    private double moneyCondition = 0.0d;    private double moneyReturn = 0,0d;    public CashReturn(String moneyCondition,String moneyReturn)    {        this.moneyReturn = double.Parse(moneyReturn);        this.moneyCondition = double.Parse(moneyCondition);    }    public override double acceptCash(double money)    {        double res = money;        if(money >= moneyCondition){            res = money - Math.Floor(money/moneyCondition)*moneyReturn;        }        return res;    }}//工厂类class CashFactory{    public static CashSuper createCashAccept(String type)    {        CashSuper cs = null;        switch(type)        {            case "正常收费":            cs = new CashNormal();            break;            case "八折":            CashRebate cr1== new CashRebate("0.8")             cs = cr1;            break;            case "满三百送一百":            CashReturn cr2 = new CashReturn("300","100")            cs = cr2;            break;        }        return cs;    }}
View Code

此时要想增加一个积分算法,如满一百积分10分,积分可兑换礼品,则加一个积分算法,传两参数(条件,返点),让它继承CashSuper,在到收费对象生成的工厂添加分支即可。

以上虽然实现了,但是商场经常性地更改打折额度和返利额度,每次维护都要改动这个工厂导致代码要重新编译部署,所以解决面对算法会时常变动的情况下,策略模式就出来解决了这个问题。

 

策略模式:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。(封装变化点)

context上下文,用一个ConcreteStrategy来配置维护一个对Strategy对象的引用。

//抽象算法类,定义了所以支持算法的公共接口abstract class Strategy{    public abstract void AlgorithmInterface();}//ContreteStrategy封装了具体算法行为,继承于Strategyclass ContreteStrategyA : Strategy{    public override void AlgorithmInterface()    {        Console.WriteLine("A实现")    }}class ContreteStrategyB : Strategy{    public override void AlgorithmInterface()    {        Console.WriteLine("B实现")    }}class ContreteStrategyC : Strategy{    public override void AlgorithmInterface()    {        Console.WriteLine("C实现")    }}//Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用class Context{    Strategy st;    public Context(Strategy st)    {        this.st = st;    }    //接口    public void ContextInterface()    {        Strategy.AlgorithmInterface();    }}//客户端static void Main(string[] args){    Context context;    context = new Context(new ContreteStrategyA());    context.ContextInterface();    Context context;    context = new Context(new ContreteStrategyB());    context.ContextInterface();    Context context;    context = new Context(new ContreteStrategyC());    context.ContextInterface();    Console.Read();}

方法二:

只需在方法一中加一个CashContext类并改写客户端代码就行:

class CashContext{    private CashSuper cs;    public CashContext(CashSuper cs)    {        this.cs = cs;    }    public double GetResult(double money)    {        return cs.acceptCash(money);    }}
CashContext cs = null;switch(type){    case "正常收费":    cs = new CashContext(new CashNormal());    break;    case "":    .    .    .}double res = cs.GetResult();

用策略与简单工厂结合改造,把客户端判断的过程转移实现隐藏:

 

策略模式