跳转至

策略#

约 547 个字 18 行代码 3 张图片 预计阅读时间 11 分钟

定义#

策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。

结构#


策略模式
  1. 上下文(Context) 维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。
  2. 策略(Strategy) 接口是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。
  3. 具体策略(ConcreteStrategies) 实现了上下文所用算法的各种不同变体。
  4. 当上下文需要运行算法时,它会在其已连接的策略对象上调用执行方法。上下文不清楚其所涉及的策略类型与算法的执行方式。
  5. 客户端(Client)会创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。

实例分析#

使用继承或实现#

示例#

Duck.java
package com.luguosong.behavioral.strategy.inheritance;

/**
 * @author luguosong
 */
public abstract class Duck {
    // 所有鸭子都会嘎嘎叫
    void quack() {
        System.out.println("嘎嘎叫");
    }

    // 所有鸭子都会游泳
    void swim() {
        System.out.println("游泳");
    }

    // 不同鸭子看起来不一样
    abstract void display();
}
MallarDuck.java
package com.luguosong.behavioral.strategy.inheritance;

/**
 * @author luguosong
 */
public class MallarDuck extends Duck {
    @Override
    void display() {
        System.out.println("看起来像绿头鸭");
    }
}
RedheadDuck.java
package com.luguosong.behavioral.strategy.inheritance;

/**
 * @author luguosong
 */
public class RedheadDuck extends Duck {
    @Override
    void display() {
        System.out.println("看起来像红头鸭");
    }
}

存在的问题#

如果Duck需要增加新的行为,比如飞行。

  • 如果直接在父类Duck中实现fly()方法,那么所有子类鸭子都将继承飞行,但并非所有鸭子都会飞行,这显然不对。
  • 可以将fly()方法定义为抽象方法,但这会导致所有子类都必须实现该方法,增加了代码的复杂性。
  • 也可以在不可以飞行的子类鸭子中覆写fly()方法,但这会导致代码重复,冗余。

代码冗余
  • 使用接口来定义飞行行为,虽然可以解决问题,但会导致代码的复杂性增加。每次增加新的行为,都需要修改对应子类的实现。

❗使用接口来定义行为,每当增加行为,所有相关子类都需要重新改写

使用策略模式#

Duck类:上下文#

Duck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 上下文
 *
 * @author luguosong
 */
public abstract class Duck {

    /*
     * 为行为接口类型声明两个引用变量。
     * 所有鸭子子类都继承它们
     * */
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    // 动态设置行为
    public void setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb;
    }

    // 动态设置行为
    public void setQuackBehavior(QuackBehavior qb) {
        quackBehavior = qb;
    }

    abstract void display();

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

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

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

飞行行为#

策略#
FlyBehavior.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 所有飞行行为实现的接口
 * <p>
 * 策略
 *
 * @author luguosong
 */
public interface FlyBehavior {
    public void fly();
}
具体策略#
FlyWithWings.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 确实能飞的鸭子的飞行行为实现
 * <p>
 * 具体策略
 *
 * @author luguosong
 */
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我正在飞行");
    }
}
FlyNoWay.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 不会飞的鸭子的飞行行为实现(像橡皮鸭和诱饵鸭)
 *
 * @author luguosong
 */
public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("我不会飞");
    }
}
FlyRocketPowered.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * @author luguosong
 */
public class FlyRocketPowered implements FlyBehavior {
    public void fly() {
        System.out.println("我正在乘火箭飞行");
    }
}

叫声行为#

策略#
QuackBehavior.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * @author luguosong
 */
public interface QuackBehavior {
    public void quack();
}
具体策略#
Quack.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 呱呱叫
 *
 * @author luguosong
 */
public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("Quack");
    }
}
MuteQuack.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 静音
 *
 * @author luguosong
 */
public class MuteQuack implements QuackBehavior {
    public void quack() {
        System.out.println("<< Silence >>");
    }
}
Squeak.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 吱吱声
 *
 * @author luguosong
 */
public class Squeak implements QuackBehavior {
    public void quack() {
        System.out.println("Squeak");
    }
}

在具体鸭子类中设置行为#

MallardDuck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 绿头鸭
 *
 * @author luguosong
 */
public class MallardDuck extends Duck {

    public MallardDuck() {
        quackBehavior = new Quack(); // 呱呱叫
        flyBehavior = new FlyWithWings(); // 确实能飞的鸭子
    }

    public void display() {
        System.out.println("我是一只真正的绿头鸭。");
    }
}
RedHeadDuck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 红头鸭
 *
 * @author luguosong
 */
public class RedHeadDuck extends Duck {

    public RedHeadDuck() {
        flyBehavior = new FlyWithWings(); // 确实能飞的鸭子
        quackBehavior = new Quack(); // 呱呱叫
    }

    public void display() {
        System.out.println("我是真正的红头鸭。");
    }
}
RubberDuck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 橡皮鸭
 *
 * @author luguosong
 */
public class RubberDuck extends Duck {

    public RubberDuck() {
        flyBehavior = new FlyNoWay(); // 橡皮鸭不会飞
        quackBehavior = new Squeak(); // 橡皮鸭会发出吱吱声
    }

    public void display() {
        System.out.println("我是只橡皮鸭。");
    }
}
DecoyDuck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 诱饵鸭
 *
 * @author luguosong
 */
public class DecoyDuck extends Duck {
    public DecoyDuck() {
        setFlyBehavior(new FlyNoWay()); // 诱饵鸭不会飞
        setQuackBehavior(new MuteQuack()); // 诱饵鸭不会叫
    }

    public void display() {
        System.out.println("我是一个诱饵鸭。");
    }
}
ModelDuck.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * 模型鸭
 *
 * @author luguosong
 */
public class ModelDuck extends Duck {
    public ModelDuck() {
        flyBehavior = new FlyNoWay(); // 模型鸭不会飞
        quackBehavior = new Quack(); // 模型鸭呱呱叫
    }

    public void display() {
        System.out.println("我是模型鸭。");
    }
}

测试代码#

MiniDuckSimulator.java
package com.luguosong.behavioral.strategy.use_strategy;

/**
 * @author luguosong
 */
public class MiniDuckSimulator {

    public static void main(String[] args) {

        Duck mallard = new MallardDuck();
        Duck rubberDuck = new RubberDuck();
        Duck decoy = new DecoyDuck();

        Duck model = new ModelDuck();

        mallard.performQuack(); // Quack
        rubberDuck.performQuack(); // Squeak
        decoy.performQuack(); // << Silence >>

        model.performFly(); // 我不会飞
        //可以动态改变行为
        model.setFlyBehavior(new FlyRocketPowered());
        model.performFly(); // 我正在乘火箭飞行
    }
}

设计模式分析#

实际使用场景#

评论