策略模式

声明 本文内容属于《Head First 设计模式》阅读笔记,文中涉及到的知识案例等直接或间接来源于该书。《Head First 设计模式》通过有趣的图表+文字的形式,让人自然学习设计模式,非常棒推荐阅读


策略模式概念

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


案例(辅助理解)

提示 策略模式使用灵活,下面只是一个简单的例子,在不同的情境下,可能有不同的表现形式。

情景介绍

       现在有一个鸭子游戏,所有的鸭子都能游泳swim,都有自己的外观display。部分鸭子能飞,而且飞的方式可能各不一样,部分鸭子能叫,可能叫的方式也各不一样。

普通方式

       因为所有的鸭子都能游泳swim,都有自己的外观display,所以使用继承的方式,创建父类鸭,父类鸭有swim以及display方法,各个不同的子类鸭均继承父类鸭,这下各个子类鸭就有了swim和display的能力了(如果有需要,还可以进行方法重写);然后对于飞行和叫,可以抽象为接口,各个子类鸭根据自己的不同的情况,实现飞行接口、叫接口即可。

使用策略模式的方式

       对于飞和叫这样的行为,单独抽取为行为两个接口,并对这两个接口分别进行算法族实现(即:一系列实现)。创建父类鸭,父类鸭本身不仅有swim和display的能力,还持有两个接口。各子类鸭只需要对这两个接口属性提供不同的策略实现即可。当子类有对飞或对叫的功能变化的需求时,可以通过setter方法进行切换。UML图如下所示:
在这里插入图片描述在父类鸭中可以将飞行为或叫行为委托给策略算法族了:
在这里插入图片描述这样一来,在子类鸭继承父类鸭时,主动指定具体的飞行为或叫行为即可,如:
在这里插入图片描述就算在程序中,想要切换子类鸭的飞行为或叫行为,只需要使用setter方法指定即可,如:
在这里插入图片描述       如果直接用子类实现飞行为或叫行为的接口的话,那么具体的行为就和具体的鸭死死绑定在了一起,程序扩展性维护性差,此时使用策略模式优势一览无疑。

上述策略模式示例中的几个核心类

  • Duck
    import com.szlaozicl.designpattern.strategy.fly.FlyBehavior;
    import com.szlaozicl.designpattern.strategy.quack.QuackBehavior;
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * 父类鸭
     *
     * 注: 如果是在各个子类中直接实现FlyBehavior或QuackBehavior的话,那么子类的
     *     飞或叫行为就是定死了的。而如果将其作为一个属性的话,那么子类中可以通
     *     过setter等方式来指定其具体实现,从而达到切换子类能力的功能。
     *
     * @author JustryDeng
     * @date 2019/10/1 19:47
     */
    public class Duck {
    
        /** 飞 属性 */
        @Setter
        @Getter
        protected FlyBehavior flyBehavior;
    
        /** 叫 属性 */
        @Setter
        @Getter
        protected QuackBehavior quackBehavior;
    
        /**
         * 所有鸭子都能游泳
         */
        public void swim() {
            System.out.println("鸭子游泳咯!");
        }
    
        /**
         * 所有鸭子都有外观
         */
        public void display() {
            System.out.println("鸭子外观 ma gia gia 的!");
        }
    
        /**
         * 调用flyBehavior的fly方法
         *
         * 即:这里将 飞 委托给了flyBehavior的具体实现
         */
        public void performFly() {
            flyBehavior.fly();
        }
    
        /**
         * 调用quackBehavior的quack方法
         *
         * 即:这里将 叫 委托给了quackBehavior的具体实现
         */
        public void performQuack() {
            quackBehavior.quack();
        }
    }
    
  • DecoyDuck
    /**
     * 诱饵鸭
     *
     * @author JustryDeng
     * @date 2019/10/1 20:05
     */
    @SuppressWarnings("unused")
    public class DecoyDuck extends Duck {
    
        /**
         * 构造方法
         *
         * 注:在构造方法中指定初始化的 飞 和 叫 的行为实现
         */
        public DecoyDuck() {
            // 诱饵鸭  能火箭助力飞, 能呱呱叫
            this.flyBehavior = new FlyRocketPowered();
            this.quackBehavior = new Quack();
        }
    
        /// other....
    }
    
  • FlyBehavior
    /**
     * 飞
     *
     * @author JustryDeng
     * @date 2019/10/1 19:50
     */
    public interface FlyBehavior {
    
        /**
         * 飞
         */
        void fly();
    }
    
  • FlyRocketPowered
    /**
     * 火箭助力飞 实现
     *
     * @author JustryDeng
     * @date 2019/10/1 20:11
     */
    public class FlyRocketPowered implements FlyBehavior {
    
        @Override
        public void fly() {
            System.out.println("火箭助力飞~");
        }
    }
    
  • FlyWithWings
    /**
     * 用翅膀飞
     *
     * @author JustryDeng
     * @date 2019/10/1 19:52
     */
    public class FlyWithWings implements FlyBehavior {
    
        @Override
        public void fly() {
            System.out.println("用翅膀飞~");
        }
    
    }
    
  • QuackBehavior
    /**
     * 叫
     *
     * @author JustryDeng
     * @date 2019/10/1 19:51
     */
    public interface QuackBehavior {
    
        /**
         * 叫
         */
        void quack();
    }
    

^_^ 如有不当之处,欢迎指正

^_^ 参考资料
        《Head First 设计模式》
Eric Freeman & Elisabeth Freeman with Kathy Sierra & Bert Bates著,O’Reilly Taiwan公司译,UMLChina改编

^_^ 测试代码托管链接
         https://github.com/JustryDeng…DesignPattern

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值