美文网首页
策略模式

策略模式

作者: yishurensheng | 来源:发表于2017-12-24 01:11 被阅读0次

    概念

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

    设计原则

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

    要点

    • 知道OO基础,并不足以让你设计出良好的OO系统。
    • 良好的OO设计必须具备可复用、可扩充、可维护三个特性。
    • 模式可以让我们建造出具有良好OO设计质量的系统。
    • 模式被认为是历经验证的OO设计经验。
    • 模式不是代码,而是针对设计问题的通用解决方案。你可以把它应用到特定应用中。
    • 模式不是被发明,而是被发现。
    • 大多数的模式和原则,都着眼于软件变化的主题。
    • 大多数的模式都允许系统局部改变独立于其他部分。
    • 我们常把系统中会变化的部分抽出来封装。
    • 模式让开发人员之间有共享的语言,能够最大化沟通的价值。

    UML图

    UML图原地址

    strategy.png

    代码实现

    先把代码贴上去,后面再慢慢解释。

    Java版本

             此版本的代码只是先实现了MallardDuck和ModelDuck这两个类的鸭子,然后进行了一些测试。剩下的RubberDuck、DecoyDuck以及RedHeadDuck都没有实现,读者如果有兴趣的话,可以自己尝试实现并进行相关的测试。

    FlyBehavior.java

    package strategy;
    
    /**
     * 所有飞行行为类必须实现的接口
     * @author ysrs
     *
     */
    public interface FlyBehavior
    {
        public void fly();
    }
    

    FlyNoWay.java

    package strategy;
    
    /**
     * 新的FlyBehavior类型,它不具有飞行能力
     * @author ysrs
     *
     */
    public class FlyNoWay implements FlyBehavior 
    {
        // 这是飞行行为的实现,给“不会”飞的鸭子用(包括橡皮鸭和诱饵鸭)
        @Override
        public void fly()
        {
            System.out.println("I can't fly!");
        }
    }
    

    FlyRocketPowered.java

    package strategy;
    
    /**
     * 新的FlyBehavior类型,它具有火箭般的飞行能力
     * @author ysrs
     *
     */
    public class FlyRocketPowered implements FlyBehavior
    {
        @Override
        public void fly()
        {
            System.out.println("I'm flying with a rocket!");
        }
    }
    

    FlyWithWings.java

    package strategy;
    
    /**
     * 新的FlyBehavior类型,它具有普通的使用翅膀的飞行能力
     * @author ysrs
     *
     */
    public class FlyWithWings implements FlyBehavior
    {
        // 这是飞行行为的实现,给”真会”飞的鸭子用。。。
        @Override
        public void fly()
        {
            System.out.println("I'm flying!!");
        }
    }
    

    QuackBehavior.java

    package strategy;
    
    /**
     * 所有呱呱叫行为类必须实现的接口
     * @author ysrs
     *
     */
    public interface QuackBehavior
    {
        public void quack();
    }
    

    Quack.java

    package strategy;
    
    /**
     * 新的QuackBehavior类型,它具呱呱叫的能力
     * @author ysrs
     *
     */
    public class Quack implements QuackBehavior
    {
        @Override
        public void quack()
        {
            System.out.println("Quack!");
        }
    }
    

    Squeak.java

    package strategy;
    
    /**
     * 新的QuackBehavior类型,它具有吱吱叫的能力
     * @author ysrs
     *
     */
    public class Squeak implements QuackBehavior
    {
        @Override
        public void quack()
        {
            System.out.println("Squeak");
        }
    }
    

    MuteQuack.java

    package strategy;
    
    /**
     * 新的QuackBehavior类型,它不具有叫的能力
     * @author ysrs
     *
     */
    public class MuteQuack implements QuackBehavior
    {
        @Override
        public void quack()
        {
            System.out.println("<< Silence >>");
        }
    }
    

    Duck.java

    package strategy;
    
    /**
     * Duck(鸭子)类
     * @author ysrs
     *
     */
    public abstract class Duck
    {
        // 为行为接口声明两个引用变量,
        // 所有鸭子子类(在同一个package中)都继承它们
        protected FlyBehavior flyBehavior;
        protected QuackBehavior quackBehavior;
        
        public Duck()
        {
            
        }
        
        public abstract void display();
        
        public void performFly()
        {
            // 委托给行为类
            flyBehavior.fly();
        }
        
        public void performQuack()
        {
            // 委托给行为类
            quackBehavior.quack();
        }
        
        public void swim()
        {
            System.out.println("All ducks float, even decoys!");
        }
        
        // 有了下面这两个函数后,以后就可以“随时”的调用这两个方法来改变鸭子的行为
        public void setFlyBehavior(FlyBehavior flyBehavior)
        {
            this.flyBehavior = flyBehavior;
        }
        public void setQuackBehavior(QuackBehavior quackBehavior)
        {
            this.quackBehavior = quackBehavior;
        }
    }
    

    MallardDuck.java

    package strategy;
    
    /**
     * MallardDuck(绿头鸭)类
     * @author ysrs
     *
     */
    public class MallardDuck extends Duck
    {
        // 因为MallardDuck类是继承Duck类,所以具有
        // quackBehavior和flyBehavior实例变量
        public MallardDuck()
        {
            // 绿头鸭使用Quack类处理呱呱叫,所以当performQuack()
            // 函数被调用时,叫的职责被委托给Quack对象,而我们得到
            // 了真正的呱呱叫,而不是吱吱叫或者叫不出声。
            quackBehavior = new Quack();
            // 使用FlyWithWings作为FlyBehavior类型
            flyBehavior = new FlyWithWings();
        }
        
        public void display()
        {
            System.out.println("I'm a real Mallard duck!");
        }
    }
    

    ModelDuck.java

    package strategy;
    
    /**
     * 新的鸭子类型,模型鸭
     * @author ysrs
     *
     */
    public class ModelDuck extends Duck
    {
        public ModelDuck()
        {
            // 一开始,我们的模型鸭是不会飞的。
            flyBehavior = new FlyNoWay();
            quackBehavior = new Quack();
        }
        
        public void display()
        {
            System.out.println("I'm a model duck!");
        }
    }
    

    MiniDuckSimulator.java

    package strategy;
    
    /**
     * 测试类,对MallardDuck和ModelDuck两个类进行测试
     * @author ysrs
     *
     */
    public class MiniDuckSimulator
    {
        public static void main(String[] args)
        {
            System.out.println("-----------------------------------------");
            System.out.println("Test Model MallardDuck!");
            Duck mallard = new MallardDuck();
            // 这会调用MallardDuck继承来的performQuack()方法,进而委托给该对象的QuackBehavior
            // 对象处理,也就是说调用继承来的quackBehavior引用对象的quack()方法。
            mallard.performQuack();
            // 和performQuack()方法一样
            mallard.performFly();
            
            System.out.println("\n-----------------------------------------");
            System.out.println("Test Model Duck!");
            Duck model = new ModelDuck();
            // 第一次调用performFly()函数,会被委托给FlyBehavior对象
            // (也就是FlyNoWay实例),该对象是在模型鸭构造函数中设置的。
            model.performFly();
            // 这会调用继承来的setter方法,把火箭动力飞行的行为设定到模型鸭中。
            // 那么,模型鸭就突然具有了火箭动力飞行能力!
            model.setFlyBehavior(new FlyRocketPowered());
            // 如果设置成功了,就意味着模型鸭可以动态的改变它的飞行行为。
            // 如果把行为的实现帮死在鸭子类中,可就无法做到这样了。
            model.performFly();
        }
    }
    

    输出结果:

    -----------------------------------------
    Test Model MallardDuck!
    Quack!
    I'm flying!
    
    -----------------------------------------
    Test Model Duck!
    I can't fly!
    I'm flying with a rocket!
    

    相关文章

      网友评论

          本文标题:策略模式

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