zoukankan      html  css  js  c++  java
  • 大话设计模式-策略模式

    策略模式

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

    优点

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

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

    不足

    策略模式就是用来封装算法的,选择具体实现的职责由客户端对象承担,并转给策略模式的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();
        }
    }
  • 相关阅读:
    hdu-3001 三进制状态压缩+dp
    最长公共子序列(LCS)
    矩阵最优路线DP
    CF-721C DAG图拓扑排序+费用DP
    拓扑排序
    BFS+二进制状态压缩 hdu-1429
    DAG最长路问题 hdu-1224
    并查集-解决区间和纠错问题 hdu-3038
    hdu 4972 根据每轮篮球赛分差求结果
    hdu 1116 欧拉回路+并查集
  • 原文地址:https://www.cnblogs.com/errornull/p/10012786.html
Copyright © 2011-2022 走看看