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

  • 相关阅读:
    Hibernate课程 初探多对多映射2-4 测试
    Hibernate课程 初探多对多映射3-1 课程总结
    Hibernate课程 初探多对多映射2-3 配置映射文件
    Hibernate课程 初探多对多映射2-2 创建持久化类和映射文件
    Hibernate课程 初探多对多映射2-1 创建数据库表
    Hibernate课程 初探多对多映射1-1 多对多应用场景
    Hibernate课程 初探一对多映射5-3 Eclipse根据表反向生成实体类
    Hibernate课程 初探一对多映射5-2 Eclipse添加数据库连接
    touch上滑加载
    touch下拉刷新
  • 原文地址:https://www.cnblogs.com/ysyn/p/3708649.html
Copyright © 2011-2022 走看看