美文网首页
1. 策略模式

1. 策略模式

作者: luhuancheng | 来源:发表于2018-03-25 23:24 被阅读0次

    设计原则

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

    定义和实现思路

    定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
    • 把算法动机使用接口抽象
    • 实现算法动机的接口,实现具体算法行为
    • 在使用此类算法的客户中,使用算法接口持有实例变量
    • 在客户中,把算法行为委托给实例变量
    • 并且可以提供setter方法,在运行时动态更改具体的算法行为

    UML模型

    策略模式.jpg

    具体代码

    /**
     * 接口封装行为
     *
     * @author luhuancheng
     * @since 2018/3/25 21:56
     */
    public interface FlyBehavior {
    
        void fly();
    
    }
    /**
     * 实现行为接口,封装具体行为
     *
     * @author luhuancheng
     * @since 2018/3/25 21:57
     */
    public class FlyWithWings implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("I'm flying!");
        }
    }
    
    
    /**
     * 接口封装行为
     *
     * @author luhuancheng
     * @since 2018/3/25 21:55
     */
    public interface QuackBehavior {
    
        void quack();
    
    }
    /**
     * 实现行为接口,封装具体行为
     *
     * @author luhuancheng
     * @since 2018/3/25 21:58
     */
    public class Quack implements QuackBehavior {
        @Override
        public void quack() {
            System.out.println("Quack!");
        }
    }
    
    /**
    *
    *抽象超类,用实例变量组合两个接口的实现类实例
    */
    public abstract class Duck {
    
        QuackBehavior quackBehavior;
    
        FlyBehavior flyBehavior;
    
        /**
         * 委托给具体的行为类
         */
        public void performQuack() {
            quackBehavior.quack();
        }
    
        /**
         * 委托给具体的行为类
         */
        public void performFly() {
            flyBehavior.fly();
        }
    
        public abstract void display();
    
        public void swim() {
            System.out.println("Duck swim");
        }
    
        /**
         * 运行时动态改变具体行为
         * @param quackBehavior
         */
        public void setQuackBehavior(QuackBehavior quackBehavior) {
            this.quackBehavior = quackBehavior;
        }
    
        /**
         * 运行时动态改变具体行为
         * @param flyBehavior
         */
            public void setFlyBehavior(FlyBehavior flyBehavior) {
            this.flyBehavior = flyBehavior;
        }
    }
    /**
     * 将不变的代码封装在超类(Duck)中,把变化的代码用接口抽象,并且使用组合的方式把接口的具体方式引入。
     * 通过委托的方式执行具体的行为
     *
     * @author luhuancheng
     * @since 2018/3/25 22:11
     */
    public class MallardDuck extends Duck {
    
        public MallardDuck() {
            quackBehavior = new Quack();
            flyBehavior = new FlyWithWings();
        }
    
        @Override
        public void display() {
            System.out.println("I'm a real Mallard duck");
        }
    }
    
    /**
     * 客户端类
     *
     * @author luhuancheng
     * @since 2018/3/25 22:16
     */
    public class Client {
    
        public static void main(String[] args) {
            Duck mallard = new MallardDuck();
            mallard.performFly();
            mallard.performQuack();
        }
    
    }
    

    调用时序图

    策略模式时序图.png

    总结

    • 我们把两类算法(即QuackBehavior、FlyBehavior)抽象为接口
    • 每一类算法都可以提供形态、方式各异的具体逻辑(此例的实现为QuackBehavior -> Quack;FlyBehavior -> FlyWithWings)
    • 在抽象超类中(Duck)使用实例变量持有以上两类算法(即QuackBehavior、FlyBehavior),并且提供了运行时动态改变算法行为的setter方法(setQuackBehavior、setFlyBehavior)。这就实现了在客户端类中,可以调用这两个方法,按需设置实现了接口(QuackBehavior、FlyBehavior)的各种算法实现。剥离了代码中经常变化的部分
    • 提供代理方法,执行算法操作(performQuack、performFly)

    相关文章

      网友评论

          本文标题:1. 策略模式

          本文链接:https://www.haomeiwen.com/subject/tvzkcftx.html