设计模式(6)---策略模式

  一、策略模式定义:

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

  分析:

  封装的算法本身是一种策略,重要的是这些算法随时可能互相替换的,这就是变化点,而封装变化点是面向对象的一种重要的思维方式。策略模式定义的这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。 

  

  二、UML类图:

  

  三、策略模式的基本代码:  

class Program
    {
        static void Main(string[] args)
        {
            Contex context;

            context = new Contex(new ConcreteStrategyA());
            context.ContexInterface();

            context = new Contex(new ConcreteStrategyB());
            context.ContexInterface();

            Console.Read();
        }
    }

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

    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实现");
        }
    }

    class Contex
    {
        Strategy strategy;

        public Contex(Strategy strategy)
        {
            this.strategy = strategy;
        }

        public void ContexInterface()
        {
            strategy.AlgorithmInterface();
        }
    }
View Code

 

  四、举例说明:    

  功能:在一家商场有三种销售方式:正常价格、打折销售和返现销售,设计一个收银软件,要求能满足上述的销售方式。本例采用策略模式,将三种销售方式封装起来。

  基本代码: 

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 money * moneyRebate;
        }
    }

    //返现策略
    class CashReturn : CashSuper
    {
        private double moneyCondition = 0d;
        private double moneyReturn = 0d;

        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double acceptCash(double money)
        {
            double result = money;

            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            }

            return result;
        }
    }

    class CashContext
    {
        private CashSuper cashSuper;

        public CashContext(CashSuper cashSuper)
        {
            this.cashSuper = cashSuper;
        }

        public double GetResult(double money)
        {
            return cashSuper.acceptCash(money);
        }
    }
View Code

  调用方式: 

cashContext = new CashContext(new CashRebate("0.8"));
totalPrices = cashContext.GetResult(Convert.ToDouble(this.tbPrice.Text) * Convert.ToDouble(this.tbNumber.Text));

 

  五、策略模式和简单工厂模式结合:

  结合后,实例化具体策略的过程由客户端转移到Context类中。修改后的CashContext: 

class CashContext
    {
        CashSuper cs = null;

        public CashContext(string type)
        {
            switch (type)
            {
                case "正常收费":
                    CashNormal cs0 = new CashNormal();
                    cs = cs0;
                    break;
                case "满300返100":
                    CashReturn cs1 = new CashReturn("300", "100");
                    break;
                case "打八折":
                    CashRebate cs2 = new CashRebate("0.8");
                    cs = cs2;
                    break;
            }
        }

        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }

  

  六、适用场景:

  1、在一个系统内有很多类,它们完成相同的功能仅在行为上有所区别,策略模式可以动态地选择一种行为。

  2、一个系统的算法使用的数据不让客户端获取。策略模式可以避免客户端涉及到一些复杂的或特别的数据。

  3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。

  4、 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。

 

  七、策略模式优缺点:

  优点:

  1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
  2、 定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
      3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。 

  缺点:

  1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

  2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。

 

 

posted @ 2014-05-05 10:35  小项目笔记  阅读(634)  评论(0编辑  收藏  举报

更多文章请关注公众号:小项目笔记

小项目笔记