设计模式学习笔记(17)策略

本文实例代码:https://github.com/JamesZBL/java_design_patterns

在策略(Strategy Pattern)模式中,一个类的行为或某个接口的实现方法可以在运行时进行更换,通常这种类型的设计模式属于行为型模式。

在策略模式中,我们通常的做法是创建一个对象来封装各种策略,创建一个上下文对象,策略对象作为上下文对象的子对象被调用,通过策略对象的改变就可以实现上下文对象在不同策略下的具体功能。现实生活中就有策略模式的例子,比如用不同的方式出行,乘坐不同的交通工具就是应用了不同的策略。

实例

居住在北京的一个人即将参加一个重要的会议,他现在面临着出行方式的选择,他的参考依据有目的地、价格、时间等。我们可以将出行方式抽象为一种策略,用接口来表示:

TransportationStrategy.java

1
2
3
public interface TransportationStrategy {
void go();
}

接口中唯一的方法就是 go(),出行。

根据不同的目的地,我们可能会乘坐不同的交通工具,比如,从北京到广州我们会选择飞机,从北京到上海我们会选择高铁,而从北京到天津,可能驾驶私家车就够了。策略是随着需求的变化而更换的,这极大的方便了同一种算法集合在不同的场景下的切换。

所以,我们定义 TransportationStrategy 接口的三种不同实现,分别用来表示乘坐三种交通工具:

TransportationAirplane.java

1
2
3
4
5
6
7
8
9
public class TransportationAirplane implements TransportationStrategy {

private static final Logger LOGGER = LoggerFactory.getLogger(TransportationAirplane.class);

@Override
public void go() {
LOGGER.info("乘飞机从北京去广州");
}
}

TransportationTrain.java

1
2
3
4
5
6
7
8
9
public class TransportationTrain implements TransportationStrategy {

private static final Logger LOGGER = LoggerFactory.getLogger(TransportationTrain.class);

@Override
public void go() {
LOGGER.info("乘高铁从北京去上海");
}
}

TransportationVehicle.java

1
2
3
4
5
6
7
8
9
public class TransportationVehicle implements TransportationStrategy {

private static final Logger LOGGER = LoggerFactory.getLogger(TransportationVehicle.class);

@Override
public void go() {
LOGGER.info("驾车从北京去天津");
}
}

现在,商人的实例一经创建,就可以调用它的 changetStrategy() 方法来更换策略了。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Application {

public static void main(String[] args) {
BusinessMan man = new BusinessMan(new TransportationAirplane());
man.transport();

man.changetStrategy(new TransportationTrain());
man.transport();

man.changetStrategy(new TransportationVehicle());
man.transport();
}
}

商人分别出席了三个地方的三个会议,通过不同的交通工具,最终都平安到达了目的地。

总结

上面例子中的 BusinessMan 就是上下文对象,它负责维护一个策略类的实例, BusinessMan 通过持有不同的策略实现类来获得不同的功能。

策略模式的几个优势:

  • 策略模式符合开闭原则,每当增加一种新的需求场景,只需要新增一个策略实现类即可,客户无需修改原有的类。
  • 使用策略模式可以减少许多 if else 语句,因为策略的不同实现本身就代表了不同的情形

策略模式的不足:

  • 客户可以使用某个策略的前提是要实现知道有这个策略,选择哪个策略是由客户决定的
  • 不支持为不同的客户适配不同的策略
分享到: