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

实现
实现鸭子的行为
考虑实现一个鸭子类,鸭子可能会有飞(Fly)和叫(Quack)的行为,所以先建立两个接口,分别代表飞的行为和叫的行为:
1 | public interface FlyBehavior { |
1 | public interface QuackBehavior { |
然后建立它们对应的类,负责实现具体的行为.
例如飞行的行为有用翅膀飞行,也可以是不会飞:
1 | public class FlyWithWings implements FlyBehavior { |
1 | public class FlyNoway implements FlyBehavior{ |
在叫的行为中,可能是呱呱叫,也可能是吱吱叫,也可能是不会叫:
1 | public class Quack implements QuackBehavior{ |
1 | public class Squeak implements QuackBehavior{ |
1 | public class MuteQuack implements QuackBehavior{ |
此时,该类的结构图就是这样了:
这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了,这么一来,有了继承的“复用”好处,但是却没有继承所带来的包袱。而我们新增一些行为,不会影响到既有的行为类,也不会影响“使用”到飞行行为的鸭子类。
整合鸭子的行为
关键在于,鸭子现在将会飞行和呱呱叫的动作“委托”别人处理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。做法是这样的:
- 首先,声明一个Duck类,在Duck类中加入两个实例变量,分别为:flyBehavior与quackBehavior。声明为接口类型,每个鸭子对象都会动态的设置这些变量以在运行时引用正确的类型。

- 现在来实现performQuack()和performFly()这两个方法:
1
2
3
4
5
6
7
8
9
10
11
12public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
想进行呱呱叫的动作,Duck对象只要交quackBehavior对象去呱呱叫就行了,想要飞的行为,只要叫flyBehavior对象
去飞就行了。我们不在乎接口的对象到底是什么,我们只关心该对象知道如何进行呱呱叫就够了。
动态行为设定
假设我们想在鸭子子类中通过“设定方法”来设定鸭子的行为,而不是在鸭子的构造期内实例化,所以:
- 在Duck类中,加入两个新方法,和一些其他的行为方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float,even decoys!");
}
}
从此以后,我们可以“随时”调用setFlyBehavior()和setQuackBehavior()这两个方法改变鸭子的行为。
查看结果
创造一个新的鸭子类型:模型鸭,其中一开始我们的鸭子是不会飞也不会叫的
1 | public class ModelDuck extends Duck { |
但是在运行中,我们如果想要改变它的行为,让它变成会飞且会呱呱叫的:
1 | public class Main { |
输出的结果为:
1 | Sorry,I can't fly. |
整体结构
此时整体的格局如下:
总结
我们把描述事情的方式稍有改变,不再把鸭子的行为说成是“一组行为”,我们开始把行为想成是“一族算法”,现在回到策略模式的定义上面再看就豁然开朗:
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。