定义
策略模式(Strategy Pattern)定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
AKA:政策模式(Policy Pattern)
使用场景
- 当许多相关的类只在行为上有所不同。策略提供了一种为一个类配置很多行为的方法;
- 实现相关算法系列。例如,可以定义不同空间/时间复杂度的算法;
- 当算法使用了客户不需要知道的数据时。使用策略模式避免暴露复杂的特定于算法的数据结构;
- 消除了一些if else条件语句。当一个类定义了很多条件语句时,应该将相关分支移动到策略中;
主要角色
- 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口。
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用。
举例
源自《Head FIRST设计模式》实现鸭子类,让这个能够飞和叫,注意会存在橡皮鸭等不会飞的鸭子,诱饵鸭等不会叫的鸭子。
代码实现
1.Duck类
public abstract class Duck
{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck(){
//构造函数,也在这里可以设置默认的FlyBehavior和QuackBehavior
}
//每个鸭子的外观不同, 在子类中实现
public abstract void display();
//执行叫的方法
public void performQuack(){
quackBehavior.quack();
}
//执行飞行的方法
public void performFly(){
flyBehavior.fly();
}
//选择飞行的方法
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
//选择叫的方法
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
2.QuackBehavior和FlyBehavior接口
public interface QuackBehavior {
void quack();
}
public interface FlyBehavior {
void fly();
}
3.具体实现Quack(呱呱叫)、Squeak(吱吱叫)、ModelQuack(不会叫)、FlyWithWings(翅膀飞)、FlyNoWay(不会飞)
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("呱呱叫");
}
}
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
public class ModelQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("什么都不做, 不会叫");
}
}
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("用翅膀飞行");
}
}
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("什么都不做, 不能飞");
}
}
4.具体实现一个普通鸭子和橡皮鸭子
//橡皮鸭子
public class RubberDuck extends Duck {
@Override
public void display() {
System.out.println("可爱的黄色橡皮鸭");
}
@Test
public void test1() throws Exception {
Duck rubberDuck = new RubberDuck();
//运行时动态改变行为
rubberDuck.setFlyBehavior(new FlyNoWay());
rubberDuck.setQuackBehavior(new Squeak());
rubberDuck.performFly();
rubberDuck.performQuack();
rubberDuck.display();
}
}
//普通绿头鸭子
public class MallardDuck extends Duck {
@Override
public void display() {
System.out.println("绿头鸭");
}
@Test
public void test1() throws Exception {
MallardDuck mallardDuck = new MallardDuck();
rubberDuck.setFlyBehavior(new FlyWithWings());
rubberDuck.setQuackBehavior(new Quack());
mallardDuck.performQuack();
mallardDuck.performFly();
mallardDuck.display();
}
}
优缺点分析
优点
- 实现了相关算法系列。Strategy类以后也可以用在别的地方。
- 提供了可以替换继承关系的办法。 无需逻辑中硬编码实现算法。易于切换、易于理解、易于扩展。
- 消除了一些if else条件语句 。将行为封装在一个个独立的Strategy类中消除了一些条件语句。
- 实现的选择 Strategy模式可以提供相同行为的不同实现。客户可以选择不同的时间及空间复杂度。
缺点
- 客户需要了解能够使用哪些算法并手动指定。不能像之前一样,我就管调用其他啥也不用管。
- Strategy和Context之间的通信开销。
- 策略模式将造成产生很多策略类。
参考
《Head FIRST设计模式》
设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
读headFirst设计模式 - 策略模式
策略模式
简说设计模式——策略模式