大话设计模式-策略模式

策略模式

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

优点

策略模式是一种定义了一系列算法的方法,从个概念上看,所有这些算法完成的都是相同的工作。只是实现不同。他可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

策略模式优化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

不足

策略模式就是用来封装算法的,选择具体实现的职责由客户端对象承担,并转给策略模式的Context对象,这本身并没有接触客户端需要选择判断的压力。不过和简单工厂模式结合后,选择具体实现的职责也可以由Context来承担。


策略模式结构演示

父类:Strategy

定义所有支持的算法的公共接口,为Context定义了一系列的可重用的算法或行为,继承有助于析取出这些算法中的公共功能。

abstract class Strategy{
    public abstract void AlgorithmInterface();
}

子类:ConcreteStrategy

封装了具体的算法或行为,继承Strategy

class ConcreteStrategyA:Strategy{
    public override void AlgorithmInterface(){
        Console.WriteLine("算法A实现");
    }
}
class ConcreteStrategyB:Strategy{
    public override void AlgorithmInterface(){
        Console.WriteLine("算法B实现");
    }
}
class ConcreteStrategyC:Strategy{
    public override void AlgorithmInterface(){
        Console.WriteLine("算法C实现");
    }
}

上下文类:Context

用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用

class Context{
    Strategy strategy;
    //初始化对象
    public Context(Strategy strategy)=>this.strategy=strategy;
    //调用具体的策略
    public void ContextInterface()=>strategy.AlgorithmInterface();
}

测试类:Program

class Program{
    static void Main(string[] args){
        Context context;
        context = new Context(new ConcreteStrategyA());
        context.ContextInterface();
        context = new Context(new ConcreteStrategyB());
        context.ContextInterface();
        context = new Context(new ConcreteStrategyC());
        context.ContextInterface();
        Console.Read();
    }
}

测试结果:控制台

算法A实现
算法B实现
算法C实现

使用策略模式改进商场促销

上下文类:CashContext

增加上下文类。通过调用上下文类,传入上下文类不同的策略来实现不同的算法或行为

class CashContext{
    private CashSuper cs;
    public CashContext(CashSuper csuper) => cs = csuper;
    public double GetResult(double money) => cs.AcceptCash(money);
}

测试类:Program

修改测试类

class Program
{
    static void Main(string[] args){
        Console.Write("请输入商品单价:");
        double foodSprice=double.Parse(Console.ReadLine());
        Console.Write("请输入商品数量:");
        double fooeNum = double.Parse(Console.ReadLine());
        Console.WriteLine($"1:原价{Environment.NewLine}2:八折{Environment.NewLine}3:满300返100");
        Console.Write("请选择优惠方式:");
        CashContext cc = null;
        switch (Console.ReadLine()){
            case "1":
                cc = new CashContext(new CashNormal());
                break;
            case "2":
                cc = new CashContext(new CashRebate(0.8));
                break;
            case "3":
                cc = new CashContext(new CashReturn(300,100));
                break;
        }
        Console.WriteLine(cc.GetResult(foodSprice*fooeNum));
        Console.ReadKey();
    }
}

使用策略模式和简单工厂模式结合改进商场促销

策略模式和简单工厂模式的结合,使客户端只需要认识一个上下文类即可,降低耦合性。

虽然Context里还是用到了switch,但是可以使用反射技术解决,在抽象工厂模式中对此有详细讲解。

上下文类:CashContext

改进CashContext,将算法的选择在上下文类构造方法中完成,创建好对应的实例。

class CashContext
{
    private CashSuper cs;
    public CashContext(string type){
        switch (type){
            case "1":
                cs = new CashNormal();
                break;
            case "2":
                cs = new CashRebate(0.8);
                break;
            case "3":
                cs = new CashReturn(300, 100);
                break;
        }
    }
    public double GetResult(double money) => cs.AcceptCash(money);
}

测试类:Program

将具体的收费算法与客户端彻底分离,更加简洁明了。

class Program{
    static void Main(string[] args){
        Console.Write("请输入商品单价:");
        double foodSprice=double.Parse(Console.ReadLine());
        Console.Write("请输入商品数量:");
        double fooeNum = double.Parse(Console.ReadLine());
        Console.WriteLine($"1:原价{Environment.NewLine}2:八折{Environment.NewLine}3:满300返100");
        Console.Write("请选择优惠方式:");
        var csuper = new CashContext(Console.ReadLine());
        Console.WriteLine(csuper.GetResult(foodSprice*fooeNum));
        Console.ReadKey();
    }
}

 

posted @ 2018-11-24 17:25  田错  阅读(204)  评论(0编辑  收藏  举报