zoukankan      html  css  js  c++  java
  • Head First设计模式之策略模式(Strategy)

            小白将从以下几点对策略模式进行解析

    • 策略模式引入的设计技巧

    • 策略模式的定义及类图

    • 策略模式的优缺点

    • 策略模式的应用场景

    • 策略模式实战

    • 总结

    零、策略模式引入的技巧

      先过一遍,放入脑海中,等看完后面所有的内容,可以结合上下文进行消化

      我们要做的不是看过、读过、理解过、消化过,而是需要将其平常化,使用模式就像使用变量一样简单。

    1. 封装变化(把会变化的部分取出并“封装”起来,好让其他部分不会受到影响,这样一来,代码变化引起的不经意后果变少,系统变得更有弹性)

    2. 针对接口编程,而不是针对实现编程(可以把具体的实现延迟到”运行时“,执行时会根据实际状况执行到真正的行为,不会在编译时直接绑死,充分利用多态使系统更有弹性)

    3. 多用组合,少用继承("有一个”可能比“是一个”更好,可以在“运行时”动态的改变具体的实现,这样使系统有很大的弹性)

    一、策略模式的定义及类图

      定义:定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。(PS:不要一带而过,停下来思考一下这句话的含义,多思考标注颜色的词语)

      类图:类图中一共有三个角色(至少三个角色),抽象策略角色具体策略角色环境角色

    1. 抽象策略角色:策略类,通常由一个接口或者抽象类实现
    2. 具体策略角色:包装了相关的算法和行为(算法和行为 对于策略模式来说是一样的,只是基于的角度不同,所以叫法不同而已
    3. 环境角色:持有一个策略类的引用,最终提供给客户端调用

       以下是UML类图:

          

     二、策略模式的优缺点

        优点:

      1. 可以动态的改变对象的行为而不需要客户端做任何的改动(从定义中就能看出来)
      2. 使用策略可以避免多重转移语句(比如 if else)。多重转移语句不便于维护,并且这种写法将采取哪一种算法的逻辑和算法的逻辑混合在一起,高耦合了
      3. 恰当的使用继承可以将公共的代码转移到父类(抽象策略角色)中,避免重复代码《此有点并非策略模式独有的优点,凡是采用继承的都可以拥有该优点

         缺点:

      1. 对于客户端来说,它必须知道所有的策略类,这样便可以根据不同的场景使用不同的策略类来完成当前的task。
      2. 策略模式的出现会引入许多的策略类,因此一般使用策略模式时需要考虑类泛滥的问题,一般4.5个具体策略类比较合适

      三、策略模式的应用场景

      1. 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为
      2. 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现
      3. 对客户隐藏具体策略(算法)的实现细节,彼此完全独立

                实际应用场景如下:(好好结合以下实际场景和上述语句进行融合)

      1. 比如买东西支付,你可以使用微信支付、支付宝支付、银行卡支持、pos机支付、零钱支持,具体使用哪种支付方式您肯定需要根据当时的场景来进行选择。
      2. 比如出行,您可以选择自行车出行、开车出行、走路出行、坐地铁出行。
      3. 再不如聊天,您可以选择微信聊天、QQ聊天、电话聊天。 等等

          根据当时环境选择哪一种方式进行后续动作便是策略。

     四、策略模式实战

      以下代码不会太复杂,只是作为示例,我这边已支付来进行实战

      抽象策略角色设计如下

    /**
     * @Author: wander
     * @Descripttion: 抽象策略角色
     * @Date: 2018年07月15日22时40分
     */
    public interface Pay {
    
        void pay(Integer money);
    
    }

      三个具体策略角色设计如下

      

    /**
     * @Author: wander
     * @Descripttion: 支付宝支付
     * @Date: 2018年07月15日22时43分
     */
    public class AliPay implements Pay {
    
        public void pay(Integer money) {
            System.out.println("支付宝支付了" + money + "元");
        }
    }
    /**
     * @Author: wander
     * @Descripttion: 微信支付
     * @Date: 2018年07月15日22时41分
     */
    public class WeChatPay implements Pay{
    
        public void pay(Integer money) {
            System.out.println("微信支付了" + money + "元");
        }
    
    }
    /**
     * @Author: wander
     * @Descripttion:
     * @Date: 2018年07月15日22时44分
     */
    public class BankCardPay implements Pay {
    
        public void pay(Integer money) {
            System.out.println("银行卡支付了" + money + "元");
        }
    }

      环境角色

    /**
     * @Author: wander
     * @Descripttion: 环境角色
     * @Date: 2018年07月15日22时49分
     */
    public class Person {
    
        private Pay pay;
    
        private Integer money;
    
        public Person(Integer money) {
            this.money = money;
        }
    
        public void pay(Pay pay) {
            pay.pay(money);
        }
    
    }

     运行类

    /**
     * @Author: wander
     * @Descripttion: 运行环境类
     * @Date: 2018年07月15日22时52分
     */
    public class Strategy {
    
        public final static Integer TEN = 10;
    
        public static void main(String[] args) {
            WeChatPay weChatPay = new WeChatPay();
            AliPay aliPay = new AliPay();
    
            Person person = new Person(TEN);
            person.pay(weChatPay);
            person.pay(aliPay);
    
        }
    
    }

    运行结果如下:

    微信支付了10元
    支付宝支付了10元

    五、总结

      当你需要根据不同的情况选择不同的方式处理问题,并且对使用者隐藏处理问题的过程,同时使用者可以随时更换处理方式而不需要做任何的改动

    便可以使用策略模式

  • 相关阅读:
    如何保证service不被系统杀死
    查找算法
    java多线程学习
    设计模式-单例
    Python2.7-内置类型
    Python2.7-内置函数
    准备要学的东西
    Python-2.7 : 编码问题及encode与decode
    【JZOJ4637】大鱼海棠【博弈论】
    【JZOJ4637】大鱼海棠【博弈论】
  • 原文地址:https://www.cnblogs.com/Shock-W/p/9314755.html
Copyright © 2011-2022 走看看