策略模式案例引入duck项目

要求:
1.有各种鸭子,比如野鸭,北京鸭,水鸭等,鸭子有各种行为,比如叫,飞行。
2.显示鸭子的信息。

传统方式实现案例

1.抽象一个父类duck,有其子类,野鸭、北京鸭、水鸭等。

代码

/** * @author 长名06 * @version 1.0 */public abstract class Duck {    public Duck(){    }    public abstract void display();    public void quack(){        System.out.println("鸭子嘎嘎叫");    }    public void swim(){        System.out.println("鸭子会游泳");    }    public void fly(){        System.out.println("鸭子会飞翔");    }}/** * @author 长名06 * @version 1.0 */public class ToyDuck extends Duck{    @Override    public void display() {        System.out.println("这是玩具鸭");    }    @Override    public void swim() {        System.out.println("玩具鸭不能游泳");    }    @Override    public void fly() {        System.out.println("玩具鸭不能飞");    }    @Override    public void quack() {        System.out.println("玩具鸭不能叫");    }}/** * @author 长名06 * @version 1.0 */public class WildDuck extends Duck{    @Override    public void display() {        System.out.println("这是野鸭");    }}/** * @author 长名06 * @version 1.0 */public class BeJingDuck extends Duck{    @Override    public void display() {        System.out.println("这是北京鸭");    }    //覆盖父类的fly方法    @Override    public void fly() {        System.out.println("北京鸭不能飞翔");    }}

传统实现问题分析

  • 1.其它鸭子,都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的。
  • 2.问题1其实是继承的问题,对类的局部改动,尤其超类的局部改动,会影响其他部分。有溢出效应。
  • 3.为了改进1问题,我们可以覆盖fly方法,来解决
  • 4.如果我们有一个玩具鸭子ToyDuck,这样就需要ToyDuck去覆盖Duck的所有实现方法 => 解决思路 策略模式(Strategy Pattern)

基本介绍

  • 1.策略模式(Strategy Pattern)中,定义算法簇,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。
  • 2.此模式,体现了几种设计原则。第一,将变化的代码从不变的代码分离;第二,针对接口编程而不是具体的类(定义策略模式接口);第三,多用组合/聚合,少用继承(客户通过组合方式使用策略)。

原理类图


说明:从上图可以看到,客户Context,有成员变量strategy或者其他的策略接口,至于需要使用到那个策略,我们可以在构造器中指定。

策略模式实现案例uml图

代码实现

/** * @author 长名06 * @version 1.0 */public abstract class Duck {    //属性,策略接口    FlyBehavior flyBehavior;    public Duck(){    }    public abstract void display();    public void quack(){        System.out.println("鸭子嘎嘎叫");    }    public void swim(){        System.out.println("鸭子会游泳");    }    public void fly(){        if(flyBehavior != null){            flyBehavior.fly();        }    }    public void setFlyBehavior(FlyBehavior flyBehavior) {        this.flyBehavior = flyBehavior;    }}/** * @author 长名06 * @version 1.0 */public interface FlyBehavior {    void fly();}/** * @author 长名06 * @version 1.0 */public class GoodFlyBehavior implements FlyBehavior{    @Override    public void fly() {        System.out.println("飞翔技术很好");    }}/** * @author 长名06 * @version 1.0 */public class NoFlyBehavior implements FlyBehavior{    @Override    public void fly() {        System.out.println("不会飞");    }}/** * @author 长名06 * @version 1.0 */public class BadFlyBehavior implements FlyBehavior{    @Override    public void fly() {        System.out.println("飞翔技术还行");    }}/** * @author 长名06 * @version 1.0 */public class ToyDuck extends Duck {    public ToyDuck(){        flyBehavior = new NoFlyBehavior();    }    @Override    public void display() {        System.out.println("这是玩具鸭");    }    @Override    public void swim() {        System.out.println("玩具鸭不能游泳");    }    @Override    public void quack() {        System.out.println("玩具鸭不能叫");    }}/** * @author 长名06 * @version 1.0 */public class WildDuck extends Duck {    public WildDuck() {        flyBehavior = new GoodFlyBehavior();    }    @Override    public void display() {        System.out.println("这是野鸭");    }}/** * @author 长名06 * @version 1.0 */public class BeJingDuck extends Duck {    public BeJingDuck(){        flyBehavior = new BadFlyBehavior();    }    @Override    public void display() {        System.out.println("这是北京鸭");    }}

策略模式在JDK-Arrays类的应用

1.JDK的Arrays的Comparator就使用了策略模式。

核心代码

      Integer[] date = {1, 8, 3, 4, 2, 9};        //1.实现降序排列,返回-1放左边,1放右边,0保持不变        //2.comparator就是实现了 Comparator接口的匿名内部类的对象 相当于策略接口的实现类        //3.public int compare(Integer o1, Integer o2) 制定了具体的处理方式        Comparator comparator = new Comparator() {            public int compare(Integer o1, Integer o2) {                if(o1 > o2){                    return 1;                }else{                    return -1;                }            }        };        /**         *  public static  void sort(T[] a, Comparator c) {         *         if (c == null) {         *             sort(a);//默认方法         *         } else {         *             if (LegacyMergeSort.userRequested)         *                 legacyMergeSort(a, c);//使用策略对象c         *             else         *                 TimSort.sort(a, 0, a.length, c, null, 0, 0);//使用策略对象c         *         }         *     }         */        Arrays.sort(date,comparator);        System.out.println(Arrays.toString(date));//使用Lambda表达式方式        Arrays.sort(date,(var1,var2) -> {            if(var1.compareTo(var2) > 0){                return 1;            }else {                return -1;            }        });        System.out.println(Arrays.toString(date));

注意事项和细节

  • 1.策略模式的关键是,分析项目中变化部分和不变部分。
  • 2.策略模式的核心思想是,多用组合/聚合,少用继承,用行为类组合。
  • 3.体现了对修改关闭,对扩展开放原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多种分支语句。
  • 4.提供了可以替换继承的方法,策略模式将算法独立封装在Strategy类中使得可以独立于使用者,是算法本身易于切换,理解,扩展。
  • 5.需要注意,添加一个策略,就要增加一个类,策略过多,就会导致类数目庞大。

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。