• headFirst设计模式——策略模式


    一、引入

      继承的最大弊端:

        改变会牵一发而动全身,造成其他子类不想要的改变。

        无限的重写方法会让人崩溃。

      利用接口:

        实现接口,也要重写方法,每个实现类都重写这个方法,代码无法复用,工作量更大。

      解决:

        将变化的行为和不变的行为分开:把变化的行为独立出来

        针对接口编程而不是对实现编程:把变化的接口独立出来,实现不同的行为,不同的实体用到该行为时,也可以复用

        

        超类中加入变化的接口,每个变量会利用多态的方式在运行时引用正确的行为类型(变化的接口的实现类)

    public abstract class Duck {
    
        FlyBehavior flyBehavior;
        
        QuackBehavior quackBehavior;
        
        public Duck() {
        }
    
        public void performFly(){
            flyBehavior.fly();
        }
        
        public void performQuack(){
            quackBehavior.quack();
        }
        
        public void swim() {
            System.out.println("Duck 会游泳");
        }
        
        public abstract void display();          //抽象的方法,每个鸭子都不一样的外貌
        
    }

         实现接口

        

         具体子类继承

         

    public class MallardDuck extends Duck {
    
        @Override
        public void display() {
            // TODO Auto-generated method stub
            System.out.println("绿头鸭");
        }
    
        public MallardDuck() {
            flyBehavior = new FlyWithWings(); 
            quackBehavior = new Quack();
        }
    
    }

        因为子类继承父类,所以具有接口的实例变量,后面会有更多模式可以用。

        仍 请 注 意 , 虽 然 我 们 把 行 为 设 定 成 具体的类(通过实例化类似 Q u a c k

        或F l y W i t h W i n g s的行为类,并指定到行为引用变量中),但是还是可以在运行时『轻易

        地』改变该行为。
        所以,目前的作法还是很有弹性的,只是初始化实例变量的作法不够弹性罢了。
        但是想一想,因为 q u a c k B e h a v i o r 实例变量是一个接口类型,能够在运行时,
        透过多态的魔法动态地指定不同的 Q u i c k B e h a v i o r 实现类给它。
        想想,如何实现鸭子,好让其行为可以在运行时改变。(再几页以后,你就会看到做这件事的代码。)
     1 public class MiniDuckSimulator {
     2 
     3     public static void main(String[] args) {
     4         Duck mallardDuck = new MallardDuck();
     5         mallardDuck.performFly();             // 实现鸭子飞行
     6         mallardDuck.performQuack();           // 实现鸭子呱呱叫
     7         mallardDuck.display();              // 绿头鸭
     8     }
     9     
    10 }

         动态的改变行为

         在Duck中放开修改行为的公共方法。

    1 //    动态设定行为
    2     public void setFlyBehavior(FlyBehavior flyBehavior) {
    3         this.flyBehavior = flyBehavior;
    4     }
    5 
    6     public void setQuackBehavior(QuackBehavior quackBehavior) {
    7         this.quackBehavior = quackBehavior;
    8     }
    9 //    从此以后,我们可以「随时」调用这两个方法改变鸭子的行为。

        

    public class FlyRocketPowered implements FlyBehavior {
    
        @Override
        public void fly() {
            // TODO Auto-generated method stub
            System.out.println("火箭动力飞行");
        }
    
    }
    1 public class MiniDuckSimulator {
    2 
    3     public static void main(String[] args) {
    4         Duck modelDuck = new ModelDuck();
    5         modelDuck.performFly();                             //不会飞
    6         modelDuck.setFlyBehavior(new FlyRocketPowered());
    7         modelDuck.performFly();                 //火箭动力飞行
    8     }
    9 }

    二、总结

       大局观:

        鸭子子类继承Duck,飞行行为实现FlyBehavior接口,鸭子叫行为实现QuackBehavior接口。

        我们描述鸭子的行为时,不再说成「一组行为」,开始把行为想成是「一族算法」。

        算法代表鸭子能做的事(不同的叫法和飞行法)。

        特别注意类之间的关系。可以是 IS-A(是一个)、HAS-A(有一个)、IMPLEMENTS(实现)。

        

         有一个的关系:每一个鸭子都有一个FlyBehavior 且有一个 QuackBehavior,鸭子将飞行和叫都委托它们代为处理。

        将两个类结合起来使用,如同本例一般就是组合(composition)。这种做法和继承不同的地方在于,鸭子行为不是继承而来,

        而是和适当的行为对象组合而来。

        本例用到三个设计原则:

        1、找出应用中可能变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

        2、针对接口编程而不是针对实现编程。

        3、多用组合,少用继承。

        使用组合建立系统具有很大的弹性,不仅可以将算法族封装成类,更可以『 在 运 行 时 动 态 地 改 变 行为』,

        只要组合的行为对象,符合正确的接口标准即可。

         

        这种模式就是『策略模式』Strategy Pattern定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。

        v>
        知道 O O基础(封装、抽象、继承、多态),并不足以让你设计出良好的 O O系统。
        v>
        良好的 O O设计必须具备可 复 用 、 可 扩 充 、 可 维 护三个特性。
        v>
        模式可以让我们建造出具 有 良 好 O O 设 计 质 量 的 系统。
        v>
        模式被认为是历经验证的 O O设计经验。
        v>
        模式不是代码,而是针对 设 计 问 题 的 通 用 解 决 方案 。 你 把 它 们 应 用 到 特 定的应用中。
        v>
        模式不是被发明,而是被发现。
        v>
        大多数的模式和原则,都着眼于软件变化的主题。
        v>
        大多数的模式都允许系统 局 部 改 变 独 立 于 其 他 部分。
        v>
        我们常把系统中,会变化的部分抽出来封装。
        v>
        模式让开发人员之间有共 享 的 语 言 , 最 大 化 沟 通的价值。
     
  • 相关阅读:
    说实话,mycat就是垃圾,不再更新
    深入理解并发/并行,阻塞/非阻塞,同步/异步
    转载:PHP 协程实现
    转载:异步、并发、协程原理
    第四章总结
    第三节 需要异常
    [第四章] 测试依赖性和异常
    第三章总结
    第三节 MVC应用程序架构和测试
    第二节 PHPUnit测试的剖析
  • 原文地址:https://www.cnblogs.com/onroad2019/p/12894459.html
Copyright © 2020-2023  润新知