zoukankan      html  css  js  c++  java
  • 一、策略模式(Strategy Pattern)《HeadFirst设计模式》读书笔记

      1.假设有一个需求,要做一个模拟鸭子的应用。首先很自然的,我们会想到使用继承,先创建一个超类Duck,然后让不同类型的鸭子继承这个超类,复用Duck中的一些属性和功能。

      2.这时我们来了一个需求,要求给一个可达鸭添加会飞的功能,为了体现OO的思想,我们不在具体的类中添加功能,还是在Duck类中添加了一个fly()方法以提高代码的复用性。但这样会导致所有类型的鸭子都继承了fly()方法,就连橡皮鸭也会,这显然是不对的。

        (1)我们可以在橡皮鸭中重写fly()方法将他覆盖掉,但是以后越来越多的鸭子类型出现后,会导致每次都需要将子类中不需要继承父类的方法覆盖掉,不仅麻烦,整体的逻辑关系也不清晰。

        (2)我们可以建立一个Flyable接口,这样想要飞的鸭子只要实现这个接口就可以了。但是还是要在特定的子类中去写实现,同样会很麻烦,而且没有实现代码的复用。

      这个问题可以总结为:我们使用继承是想提高代码的复用性,但是有的子类又有自己的特殊需求,如何有条理的按需定制这些方法呢?

      3.使用组合:

        (1)我们可以将Duck超类中的内容分为两部分:变化的和不会变化的。所有鸭子都具有的特征和行为就是基本不会变化的,我们使用继承处理这一部分,如果以后这些行为需要改变,也只需要在Duck超类中改动就可以了;而fly()行为就是会变化的,不同类型的鸭子会有不同的飞行姿势,还可能不会飞,这一部分我们可以使用组合。

        (2)创建一个FlyBehavior接口,对于不同的飞行行为都实现这个接口,对应具体的实现类,如FlyWithWings,FlyNoWay。

    public interface FlyBehavior {
        void fly();
    }
    
    public class FlyWithWings  implements FlyBehavior{
        @Override
        public void fly() {
            System.out.println("i can fly with wings");
        }
    }
    
    public class FlyNoWay implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("I can't fly");
        }
    }

        (3)在Duck中以成员变量的方式组合我们想要的功能,声明成接口类型,如FlyBehavior。再写一个方法叫perfomFly(),在方法内调用FlyBehavior接口的fly()方法,这里又体现了多态的思想。

    public abstract class Duck {
        private String color;
        FlyBehavior flyBehavior;
        abstract void display();
        //所有的鸭子都会游泳
        public void swim(){
            System.out.println("all ducks can swim");
        }
        //通过组合实现fly的功能
        public void performFly(){
            flyBehavior.fly();
        }
    }

        而该成员变量接口具体的实例在子类创建对象时,通过构造方法传递进来(暂时,后面会用其他设计模式优化)。额外的也可以通过增加set()方法动态的改变鸭子的行为。

    public class PsyDuck extends Duck {
        @Override
        void display() {
            System.out.println("I am a PsyDuck");
        }
        //暂时通过构造方法传入FlyBehavior的实现类
        public PsyDuck(FlyBehavior flyBehavior) {
            this.flyBehavior = flyBehavior;
        }
    }

       测试一下:

    public class MainTest {
        public static void main(String[] args) {
            PsyDuck psyDuck = new PsyDuck(new FlyWithWings());
            psyDuck.performFly();
        }
    }

        打印结果为:

      

        在上面的例子中我们就使用了策略模式。

     4.策略模式(Strategy Pattern):

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

        解释:刚刚我们写的FlyBehavior的两个实现类FlyWithWings和FlyNoWay就是一族算法,说白了就是一组行为,当需要不同具体行为的时候,他们之间可以替换,这些行为发生变化时并不会影响到Duck和它的子类,因为在Duck中我们是使用多态的方式通过接口声明的。

      5.总结:

        (1)将变化的部分封装起来

        (2)使用组合

        (3)使用多态,面向接口编程

  • 相关阅读:
    返回顶部
    判断元素在数组中
    Vue.js相关知识4-路由
    Vue.js相关知识3-路由
    Vue.js相关知识2-组件
    Vue.js相关知识1
    element表格左右滚动条在总计的上面怎么解决
    JAVA的安装及配置环境变量
    uni-app中使用vuex
    前端常用设计模式
  • 原文地址:https://www.cnblogs.com/advancedcz/p/13072437.html
Copyright © 2011-2022 走看看