策略模式

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

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

一个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封装了具体算法行为,继承于Strategy
class 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();

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

 

posted @ 2014-11-16 15:08  R_bin  阅读(140)  评论(0编辑  收藏  举报