策略#
约 547 个字 18 行代码 3 张图片 预计阅读时间 11 分钟
定义#
策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
结构#

上下文(Context)
维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。策略(Strategy)
接口是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。具体策略(ConcreteStrategies)
实现了上下文所用算法的各种不同变体。- 当上下文需要运行算法时,它会在其已连接的策略对象上调用执行方法。上下文不清楚其所涉及的策略类型与算法的执行方式。
- 客户端(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(); // 我正在乘火箭飞行
}
}