策略模式

来源:互联网 发布:微点主动防御软件 编辑:程序博客网 时间:2024/06/10 01:40

思维过程

业务场景

一个系统里面有鸭子类(抽象父类),有各种各样的鸭子(子类),这些鸭子都有叫quack、游泳swim、显示display方法。不同的鸭子显示不同的外观。如RedHeadDuck红头鸭,MallarDuck绿头鸭。初始基本关系如下:

这里写图片描述

问题一

现在有一些鸭子能飞,有一些不能飞;有一些鸭子能叫,有一些鸭子不能叫;怎么去定义方法呢?

不佳解决方法一

  • 实现:在父类中写一个抽象的公共的fly方法,子类中进行重写。能飞的鸭子实现飞的行为,不能飞的鸭子实现空的行为。叫quack方法同理。
  • 问题:每添加一个鸭子子类都要重写fly和quack方法,这简直就是噩梦。而且
  • 思考:继承可能不是解决办法,可以想想接口。

不佳解决方法二

  • 实现 : 针对飞和叫这两种行为,可以定义两个接口,有这样行为的鸭子便实现这两个接口即可。这样没有这些行为的鸭子就没有这些行为。类图如下:

这里写图片描述

  • 解决:会飞的鸭子才能飞,会叫的鸭子才能叫。
  • 问题:接口不具有实现代码,如果有50个鸭子子类,都会飞,那么就要实现50次,代码无法复用!!!

设计原则之独立原则

找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。这样系统中的某部分改变就不会影响其他部分。

由于行为变成动态的了,所以需要提供动态设定行为的方法,那么我们遵循下面的原则

设计原则之针对接口编程

针对接口编程,而不是针对实现编程

策略模式解决方法三

这样来设计这些动态改变的行为:

这样的设计,可以让飞行和呱呱叫的动作被其它对象复用,因为这些行为已经和鸭子类无关了。我们可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”飞行行为的鸭子类。

在鸭子Duck的父类中,持有这些行为(算法)的引用,利用多态,就可以动态地改变这些行为了。最终类图如下:

Duck类中的属性说明:

  • flyBehaviour:有一个飞行行为FlyBehaviour,组合,飞行行为委托给它去处理
  • quackBehaviour:有一个叫的行为QuackBehaviour,组合,叫的行为委托给它去处理

Duck类中的方法说明:

  • swim:鸭子游泳,同样的行为(算法),不会改变
  • display:鸭子展现,抽象方法,每种鸭子有自己独特的展现方式,有自己实现
  • performQuack:由quackBehaviour去执行quack方法
  • performFly:由flayBehaviour去执行fly方法
  • setQuackBehaviour:设置叫的行为(算法)
  • setFlyBehaviour:设置飞的行为(算法)

设计原则之组合原则

多用组合,少用继承

通过组合建立系统具有很大的弹性。

策略模式

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

代码展现

飞行行为的代码

飞行接口

/** * 飞行行为的接口 */public interface FlyBehaviour {    /**     * 飞行行为      */    public void fly();}

用翅膀飞

/** * 用翅膀飞 */public class FlyWithWings implements FlyBehaviour {    @Override    public void fly() {        System.out.println("用翅膀飞~");    }}

不会飞

/** * 不能飞 */public class FlyNoWay implements FlyBehaviour {    @Override    public void fly() {        System.out.println("不能飞..");    }}

叫的行为的代码

叫的行为的接口

/** * 鸭子叫的行为接口 */public interface QuackBehaviour {    /**     * 叫的行为方法     */    public void quack();}

呱呱叫

/** * 呱呱叫 */public class Quack implements QuackBehaviour {    @Override    public void quack() {        System.out.println("呱呱叫~");    }}

吱吱叫

/** * 吱吱叫 */public class Squack implements QuackBehaviour {    @Override    public void quack() {        System.out.println("吱吱叫~");    }}

不会叫

/** * 不会叫 */public class MuteQuack implements QuackBehaviour {    @Override    public void quack() {        System.out.println("不会叫..");    }}

关于鸭子类的代码

鸭子父类

/** * 鸭子的父类 */public abstract class Duck {    /** 飞行行为 */    protected FlyBehaviour flyBehaviour;    /** 叫的行为 */    protected QuackBehaviour quackBehaviour;    /**     * 鸭子展现     */    public abstract void display();    /**     * 鸭子游泳     */    public void swim() {        System.out.println("鸭子在游泳~~");    }    /**     * 鸭子飞行     */    public void performFly() {        flyBehaviour.fly();    }    /**     * 鸭子叫     */    public void performQuack() {        quackBehaviour.quack();    }    public FlyBehaviour getFlyBehaviour() {        return flyBehaviour;    }    public void setFlyBehaviour(FlyBehaviour flyBehaviour) {        this.flyBehaviour = flyBehaviour;    }    public QuackBehaviour getQuackBehaviour() {        return quackBehaviour;    }    public void setQuackBehaviour(QuackBehaviour quackBehaviour) {        this.quackBehaviour = quackBehaviour;    }}

绿头鸭

/** * 绿头鸭,默认会飞会呱呱叫 */public class MallarDuck extends Duck{    /**     * 在构造方法中,初始化飞行和叫的行为(后期会有更好的处理)     */    public MallarDuck() {        flyBehaviour = new FlyWithWings();        quackBehaviour = new Quack();    }    @Override    public void display() {        System.out.println("绿头鸭");    }}

红头鸭

/** * 红头鸭,默认会飞会呱呱叫 */public class RedHeadDuck extends Duck{    public RedHeadDuck() {        flyBehaviour = new FlyWithWings();        quackBehaviour = new Quack();    }    @Override    public void display() {        System.out.println("红头鸭");    }}

橡皮鸭

/** * 橡皮鸭,默认不会飞,会呱呱叫 */public class RubberDuck extends Duck{    public RubberDuck() {        flyBehaviour = new FlyNoWay();        quackBehaviour = new Quack();    }    @Override    public void display() {        System.out.println("橡皮鸭");    }}

诱饵鸭

/** * 诱饵鸭,默认不会飞,不会叫 */public class DecoyDuck extends Duck {    public DecoyDuck() {        flyBehaviour = new FlyNoWay();        quackBehaviour = new MuteQuack();    }    @Override    public void display() {        System.out.println("诱饵鸭");    }}

测试代码

public class TestClient {    public static void showDuck(Duck duck) {        duck.display();        duck.performFly();        duck.performQuack();    }    public static void main(String[] args) {        Duck duck = new RedHeadDuck();        showDuck(duck);        System.out.println("------让此duck不会飞,和吱吱叫-----");        duck.setFlyBehaviour(new FlyNoWay());        duck.setQuackBehaviour(new Squack());        showDuck(duck);    }}

输出结果如下:

红头鸭
用翅膀飞~
呱呱叫~
——让此duck不会飞,和吱吱叫—–
红头鸭
不能飞..
吱吱叫~

0 0
原创粉丝点击