Java设计模式之【策略模式】

策略模式

  • 业务需求
    编写鸭子项目,具体需求如下:
    • 有各种鸭子,如:野鸭、北京鸭子、水鸭等。鸭子有各种行为,如:叫、飞行等
    • 显示鸭子的信息。
  • 解决方案
    • 传统方案
      • 方式:编写一个父类,各种具体的类继承父类
      • 问题分析:
        • 其他鸭子都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的
        • 上述问题是继承带来的问题:对类的局部改动,尤其是超类的局部改动,会影响其他部分。会有溢出效应
      • 解决方案:
        • 为了改进上述问题,我们可以通过覆盖fly方法来解决—》覆盖解决
        • 使用覆盖解决有会出现如下问题:
          如果有一个玩具鸭子ToyDuck,这样就需要ToyDuck去覆盖Duck的所有实现的方法。—》策略模式
    • 策略模式(strategy pattern)
      • 基本介绍
        • 策略模式中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
        • 算法体现了几个设计原则
          • 把变化的代码从不变的代码中分离出来;
          • 针对接口编程而不是具体类(定义策略接口);
          • 多重组合/聚合,少用继承(客户通过组合方式使用策略)
      • 原理类图
        image-20211107113350804
        从上图可以看到,客户Context有成员变量strategy或者其他的策略接口,至于需要使用到哪个策略,我们可以在构造器中指定
      • 使用策略模式解决鸭子问题
        思路分析:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。
        原则:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者。
      • 业务类图
        image-20211107152010992
      • 代码实现
        • 编写FlyBehavior策略接口
        package ltd.huazhongyang.strategy.strategy.interfaces;
        public interface FlyBehavior {
            /**
             * 子类具体实现
             */
            void fly();
        }
        
        • 编写飞行技术高超类,并实现FlyBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        public class GoodFlyBehavior implements FlyBehavior {
            @Override
            public void fly() {
                System.out.println("飞行技术呱呱叫。。。");
            }
        }
        
        • 编写飞行技术一般类,并实现FlyBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        public class BadFlyBehavior implements FlyBehavior {
            @Override
            public void fly() {
                System.out.println("飞行技术就那样。。。");
            }
        }
        
        • 编写不会飞行技术类,并实现FlyBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        public class NoFlyBehavior implements FlyBehavior {
            @Override
            public void fly() {
                System.out.println("没有遨游太空的权力。。。");
            }
        }
        
        • 编写QuackBehavior策略接口
        package ltd.huazhongyang.strategy.strategy.interfaces;
        public interface QuackBehavior {
            /**
             * 子类具体实现
             */
            void quack();
        }
        
        • 编写嘎嘎叫类,并实现QuackBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        public class GaGaQuackBehavior implements QuackBehavior {
            @Override
            public void quack() {
                System.out.println("嘎嘎叫。。。");
            }
        }
        
        • 编写咯咯叫类,并实现QuackBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        public class GeGeQuackBehavior implements QuackBehavior {
            @Override
            public void quack() {
                System.out.println("咯咯叫。。。");
            }
        }
        
        • 编写不会叫类,并实现QuackBehavior接口
        package ltd.huazhongyang.strategy.strategy.interfaces.impl;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        public class NoQuackBehavior implements QuackBehavior {
        
            @Override
            public void quack() {
                System.out.println("不会叫。。。");
            }
        }
        
        • 编写Duck抽象类,并聚合FlyBehavior和QuackBehavior接口类
        package ltd.huazhongyang.strategy.strategy.abstracts;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        public abstract class Duck {
            /**
             *  策略接口
             */
            private FlyBehavior flyBehavior ;
            private QuackBehavior quackBehavior ;
            public Duck(){
            }
            public void setFlyBehavior(FlyBehavior flyBehavior) {
                this.flyBehavior = flyBehavior;
            }
            public void setQuackBehavior(QuackBehavior quackBehavior) {
                this.quackBehavior = quackBehavior;
            }
            public void fly(){
                 if(flyBehavior != null){
                     flyBehavior.fly();
                 }
            }
            public void quack(){
                if(quackBehavior != null){
                    quackBehavior.quack();
                }
            }
            public abstract void display();//显示鸭子信息
        }
        
        • 编写野鸭子类,并继承Duck超类以及实现相关方法
        package ltd.huazhongyang.strategy.strategy.abstracts.entends;
        import ltd.huazhongyang.strategy.strategy.abstracts.Duck;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.GaGaQuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.GoodFlyBehavior;
        public class WildDuck extends Duck {
            /**
             * 构造器  传入FlyBehavior
             */
            public WildDuck(){
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(new GaGaQuackBehavior());
            }
            public WildDuck(FlyBehavior flyBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(new GaGaQuackBehavior());
            }
            public WildDuck(QuackBehavior quackBehavior) {
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(quackBehavior);
            }
            public WildDuck(FlyBehavior flyBehavior,QuackBehavior quackBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(quackBehavior);
            }
            @Override
            public void display() {
                System.out.println("这是野鸭子~~~~~");
            }
        }
        
        • 编写北京鸭子类,并继承Duck超类以及实现相关方法
        package ltd.huazhongyang.strategy.strategy.abstracts.entends;
        import ltd.huazhongyang.strategy.strategy.abstracts.Duck;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.GeGeQuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.GoodFlyBehavior;
        public class PakingDuck extends Duck {
            /**
             * 构造器  传入FlyBehavior
             */
            public PakingDuck(){
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(new GeGeQuackBehavior());
            }
            public PakingDuck(FlyBehavior flyBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(new GeGeQuackBehavior());
            }
            public PakingDuck(QuackBehavior quackBehavior) {
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(quackBehavior);
            }
            public PakingDuck(FlyBehavior flyBehavior,QuackBehavior quackBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(quackBehavior);
            }
            @Override
            public void display() {
                System.out.println("这是北京鸭子");
            }
        }
        
        • 编写玩具鸭子类,并继承Duck超类以及实现相关方法
        package ltd.huazhongyang.strategy.strategy.abstracts.entends;
        import ltd.huazhongyang.strategy.strategy.abstracts.Duck;
        import ltd.huazhongyang.strategy.strategy.interfaces.FlyBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.QuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.NoQuackBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.GoodFlyBehavior;
        public class ToyDuck extends Duck {
            /**
             * 构造器  传入FlyBehavior
             */
            public ToyDuck(){
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(new NoQuackBehavior());
            }
            public ToyDuck(FlyBehavior flyBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(new NoQuackBehavior());
            }
            public ToyDuck(QuackBehavior quackBehavior) {
                super.setFlyBehavior(new GoodFlyBehavior());
                super.setQuackBehavior(quackBehavior);
            }
            public ToyDuck(FlyBehavior flyBehavior,QuackBehavior quackBehavior) {
                super.setFlyBehavior(flyBehavior);
                super.setQuackBehavior(quackBehavior);
            }
            @Override
            public void display() {
                System.out.println("这是玩具鸭子~~~~~");
            }
        }
        
        • 创建启动类
        package ltd.huazhongyang.strategy.strategy;
        import ltd.huazhongyang.strategy.strategy.abstracts.entends.PakingDuck;
        import ltd.huazhongyang.strategy.strategy.abstracts.entends.WildDuck;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.BadFlyBehavior;
        import ltd.huazhongyang.strategy.strategy.interfaces.impl.NoQuackBehavior;
        public class Client {
            public static void main(String[] args) {
                WildDuck wildDuck = new WildDuck();
                wildDuck.display();
                wildDuck.fly();
                wildDuck.quack();
                PakingDuck pakingDuck = new PakingDuck();
                pakingDuck.display();
                pakingDuck.fly();
                pakingDuck.quack();
                PakingDuck pakingDuck1 = new PakingDuck(new BadFlyBehavior(),new NoQuackBehavior());
                pakingDuck1.display();
                pakingDuck1.fly();
                pakingDuck1.quack();
            }
        }
        
        • 测试结果
          image-20211107162417816
      • 注意事项和细节
        • 关键:分析项目中变化部分与不变部分
        • 核心思想是:多用组合/聚合 ,少用继承;多用行为类组合,而不是行为的继承,使得更有弹性。体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if…else if…else)提供了可以替换继承关系的办法;策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使得它易于切换、理解扩展。
        • 需要注意的是:每添加一个策略就需要添加一个类,当策略过多是会导致类数目庞大。
  • 策略模式在JDK-Arrays应用的源码分析
    • JDK中的Arrays的Comparator就使用了策略模式
    • 具体实现:
      对数组进行排序
      • 方式一
        • 说明:
          1.实现了Comparator 接口(策略接口) ,匿名类 对象 new Comparator() {。。。。}
          2.对象 new Comparator() {。。。} 就是实现了策略接口的对象
          3.public int compare(Integer o1, Integer o2) {} 指定具体的处理方式
        • 代码实现:
        Integer[] data = {1,9,5,3,4,6,8,7,2};
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        //根据策略模式进行排序
        Arrays.sort(data,comparator);
        System.out.println(Arrays.toString(data));
        
        • 测试结果
          image-20211107223920397
        • sort源码分析
        public static <T> void sort(T[] a, Comparator<? super T> c) {
            if (c == null) {
                sort(a);
            } else {
                if (LegacyMergeSort.userRequested)
                    legacyMergeSort(a, c);
                else
                    TimSort.sort(a, 0, a.length, c, null, 0, 0);
            }
        }
        
      • 方式二
        • 说明:使用Lambda表达式实现策略模式
        • 代码实现
        Integer[] data1 = {1,9,5,3,6,4,8,7,2};
        Arrays.sort(data1,(var1,var2) ->{
            return Integer.compare(var1.compareTo(var2), 0);
        });
        System.out.println(Arrays.toString(data1));
        
        • 测试结果
          image-20211107223920397
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值