设计模式----策略模式

本文经过简单的模拟鸭子应用作起,在模拟鸭子游戏中,会出现各类鸭子,鸭子能够游泳、能够呱呱叫。java


看看模拟鸭子程序的初期类图

image-20200531150923842

如今客户想让鸭子能够飞行,因而赞成了这个需求,类图变成了下面这样算法

image-20200531151256672

这是,可怕的问题发生了,有许多“橡皮鸭子”能够在游戏界面飞来飞去,这是在设计上的疏忽,由于在超类上加上fly(),就会致使全部的子类都具有fly(),连那些不应具有fly()的子类也没法免除。设计模式


利用接口如何?

我能够把fly()从超类中取出来,放进一个“Flyable接口”中。这么一来,只有会飞的鸭子才实现此接口。一样的方式,也能够用来设计一个“Quackable接口”,由于不是全部的鸭子都会叫。 测试

image-20200531151841312

咱们知道,并不是“全部”的子类都具备飞行和呱呱叫的行为,因此继承并非适当的解决方式。虽然Flyable与Quackable能够解决“一部分”问题(不会再有会飞的橡皮鸭),可是却形成代码没法复用,这只能算是从一个恶梦跳进另外一个恶梦 。spa

这个时候咱们想到一个设计原则插件

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

分开变化和不会变化的部分

咱们知道Duck类内的fly()和quack()会随着鸭子的不一样而改变。 设计

下面开始设计鸭子的行为3d

image-20200531152351585


整合鸭子的行为

首先,在Duck类中“加入两个实例变量” ,分别为“flyBehavior”与“quackBehavior”,声明为接口类型(而不是具体类实现类型),每一个鸭子对象都会动态地设置这些变量以在运行时引用正确的行为类型 。code

编写Duck类orm

public abstract class Duck {
    //为行为接口类型声明两个引用变量,全部鸭子类都继承它们
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    abstract void display();

    public void performFly() {
        //委托给行为类
        flyBehavior.fly();
    }

    public void performQuack() {
         //委托给行为类
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
}

编写MallardDuck类

public class MallardDuck extends Duck {

    public MallardDuck() {

        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();

    }

    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

编写ModelDuck类

public class ModelDuck extends Duck {
    public ModelDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }

    public void display() {
        System.out.println("I'm a model duck");
    }
}

编写FlyBehavior接口与两个行为实现类

FlyBehavior接口

public interface FlyBehavior {
    public void fly();
}

FlyNoWay

public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("I can't fly");
    }
}

FlyWithWings

public class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("I'm flying!!");
    }
}

编写QuackBehavior接口与三个实现类

public interface QuackBehavior {
    public void quack();
}

Quack实现类

public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("Quack");
    }
}

MuteQuack

public class MuteQuack implements QuackBehavior {
    public void quack() {
        System.out.println("<< Silence >>");
    }
}

Squack

public class Squeak implements QuackBehavior {
    public void quack() {
        System.out.println("Squeak");
    }
}

编写测试类

public class MiniDuckSimulator {
 
    public static void main(String[] args) {
 
        MallardDuck    mallard = new MallardDuck();
        mallard.display();
        mallard.performQuack();
        mallard.performFly();

 
        Duck model = new ModelDuck();
        model.display();
        model.performQuack();
        model.performFly();
    }
}

运行结果

image-20200531162244767


策略模式的定义

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法, 将每一个算法都封装起来, 而且使它们之间能够互换。 )

通用类图

image-20200531162828790

策略模式使用的就是面向对象的继承和多态机制, 很是容易理解和掌握, 咱们再来看看策略模式的三个角色:

  • Context封装角色
    它也叫作上下文角色, 起承上启下封装做用, 屏蔽高层模块对策略、 算法的直接访问,封装可能存在的变化。
  • Strategy抽象策略角色
    策略、 算法家族的抽象, 一般为接口, 定义每一个策略或算法必须具备的方法和属性。 各位看官可能要问了, 类图中的AlgorithmInterface是什么意思, 嘿嘿, algorithm是“运算法则”的意思, 结合起来意思就明白了吧。
  • ConcreteStrategy具体策略角色

    实现抽象策略中的操做, 该类含有具体的算法

策略模式的应用

策略模式的优势

  • 算法能够自由切换
  • 避免使用多重条件判断

    若是没有策略模式, 咱们想一想看会是什么样子? 一个策略家族有5个策略算法, 一会要使用A策略, 一会要使用B策略, 怎么设计呢? 使用多重的条件语句? 多重条件语句不易维护, 并且出错的几率大大加强。 使用策略模式后, 能够由其余模块决定采用何种策略, 策略家族对外提供的访问接口就是封装类, 简化了操做, 同时避免了条件语句判断。

  • 扩展性良好

    在现有的系统中增长一个策略太容易了, 只要实现接口就能够了, 其余都不用修改, 相似于一个可反复拆卸的插件, 这大大地符合了OCP原则。

策略模式的缺点

  • 策略类数量增多

    每个策略都是一个类, 复用的可能性很小, 类数量增多。

  • 全部的策略类都须要对外暴露

策略模式的使用场景

  • 多个类只有在算法或行为上稍有不一样的场景
  • 算法须要自由切换的场景
    例如, 算法的选择是由使用者决定的, 或者算法始终在进化, 特别是一些站在技术前沿的行业, 连业务专家都没法给你保证这样的系统规则可以存在多长时间, 在这种状况下策略模式是你最好的助手。
  • 须要屏蔽算法规则的场景

参考书籍:《Head First 设计模式》《设计模式之禅》

相关文章
相关标签/搜索