首页 > 学院 > 开发设计 > 正文

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

2019-11-14 16:40:49
字体:
来源:转载
供稿:网友

  一、策略模式定义:

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

 

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表