• HeadFirst设计模式读书笔记之策略模式


    1. 例子

    1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在

    超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超类,实现自己的display()方法来表现鸭子的行为,像下面这样:

    2. 但如果要加一个可以吃火锅的鸭子呢,类就会变成这样:


    可以看到,每添加一个新的鸭子就要修改超类一次,而不需要这些多余行为的鸭子不得不
    继承这些多余的方法,这样每只鸭子都是全能的,一点差异都没有,代码失去了意义,这样做既不安全,又不方便扩展.想想,每增加一个鸭子,就要
    修改超类一次,如果有成千上万种鸭子岂不麻烦死了.总结一下,有以下几个缺点:

    1. 代码在多个子类重复

    2. 运行时的行为不容易改变

    3. 难以知道所有鸭子的全部行为(有些鸭子的行为可能定义在子类,并且无法重用)

    4. 牵一发而动全身,改了超类,其他鸭子继承的行为也会改变

    3. 新的思路重构代码

    1. 将容易变化的需求与不变化的需求分开处理

    2. 将鸭子和鸭子的各种行为分开处理,通过接口来组合他们,这就是针对接口编程

    3. 让鸭子持有定义行为的接口,将鸭子的行为''委托' 给别人处理,不直接定义在鸭子类中

    4. 将鸭子的行为通过接口来实现,运行时通过多态来指定具体实现


    2. 关键代码

    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:03
     */
    public interface FlyBehavior {
    
      // 飞飞飞
      void fly();
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:04
     */
    public interface QuackBehavior {
    
      // 呱呱叫
      void quack();
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:06
     */
    public abstract class Duck {
    
      FlyBehavior flyBehavior;
    
      QuackBehavior quackBehavior;
    
      public Duck(FlyBehavior flyBehavior, QuackBehavior quackBehavior) {
        this.flyBehavior = flyBehavior;
        this.quackBehavior = quackBehavior;
      }
    
      public Duck() {
      }
    
      public abstract void display();
    
      public void setFlyBehavior(FlyBehavior flyBehavior){
        this.flyBehavior = flyBehavior;
      }
    
      public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
      }
    
      public void performQuack() {
        quackBehavior.quack();
      }
    
      public void performFly() {
        flyBehavior.fly();
      }
    
      public void swim() {
        System.out.println("All ducks float, even decoys!");
      }
    }
    
    public class FlyWithWings implements FlyBehavior {
    
      @Override
      public void fly() {
        System.out.println("鸭子在贡嘎山脉广袤的森林中飞行");
      }
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:18
     */
    public class Quack implements QuackBehavior {
      @Override
      public void quack() {
        System.out.println("春天到了,鸭子嘎嘎叫");
      }
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:54
     */
    public class FlyRocketPowerd implements FlyBehavior {
      @Override
      public void fly() {
        System.out.println("火箭式助推飞行装置,启动!");
      }
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:18
     */
    public class Squeak implements QuackBehavior {
      @Override
      public void quack() {
        System.out.println("鸭子发出了吱吱的娇嗔");
      }
    }
    
    /**
     * @Author: Lisa
     * @Date: 2018/11/16 10:37
     */
    public class MiniDuckSimulator {
      public static void main(String args[]) {
        Duck mallard = new MallardDuck(new FlyWithWings(),new Quack());
        mallard.performQuack();
        mallard.performFly();
        mallard.setFlyBehavior(new FlyRocketPowerd());
        mallard.setQuackBehavior(new Squeak());
        mallard.performFly();
        mallard.performQuack();
      }
    }
    
    结果:
    春天到了,鸭子嘎嘎叫
    鸭子在贡嘎山脉广袤的森林中飞行
    火箭式助推飞行装置,启动!
    鸭子发出了吱吱的娇嗔
    

    3. 学到的设计原则

    1. 找出应用中可能需要变化之处,把他们独立出来,不和那些不需要变化的代码混到一起
    2. 针对接口编程,而不是针对实现编程
    3. 多用组合,少用继承

    4. 策略模式的定义

    策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

  • 相关阅读:
    复杂报表的存储过程
    Jquery中使用setInterval和setTimeout
    Jquery EasyUi实战教程布局篇
    枚举enum
    myGeneration代码生成器
    带有分页的存储过程
    应用临时表的存储过程
    缓存类的写法
    HDU4706 Children's Day
    HDU4706 Children's Day
  • 原文地址:https://www.cnblogs.com/Lothlorien/p/9994487.html
Copyright © 2020-2023  润新知