策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
前言
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装在一个具有共同接口的独立类中,使得它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。这种模式在很多场景下都非常实用,例如在不同的情况下需要执行不同的业务逻辑时,或者需要动态地改变对象的行为时。诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
一、策略模式的核心角色
- Context(上下文):负责维护对策略对象的引用,并提供一个方法来设置策略对象。
- Strategy(策略):定义所有支持的算法的公共接口。具体的策略实现这个接口,提供具体的算法实现。
- ConcreteStrategy(具体策略):实现策略接口的具体类,提供具体的算法实现。
二、具体实现
1.创建一个策略接口
代码如下(示例):
// 策略接口
public interface Strategy {
void execute();
}
2.创建实现策略接口的具体策略实体类
代码如下(示例):
// 具体策略A
public class ConcreteStrategyA implements Strategy {
@Override public void execute() {
System.out.println("执行策略A");
}
}
// 具体策略B
public class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("执行策略B");
}
}
3.创建 Context 类。
// 上下文
public class Context {
private Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
4.创建客户端类使用 Context 来查看当它改变策略 Strategy 时的行为变化。
// 客户端
public class Client {
public static void main(String[] args) {
Context context = new Context();
// 设置策略A
context.setStrategy(new ConcreteStrategyA());
context.executeStrategy(); // 输出:执行策略A
// 设置策略B
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy(); // 输出:执行策略B
}
在这个示例中,我们定义了一个策略接口Strategy
,以及两个具体策略类ConcreteStrategyA
和ConcreteStrategyB
。Context
类负责维护对策略对象的引用,并提供一个方法来设置策略对象。客户端可以通过设置不同的策略对象来改变Context
的行为。
三、使用场景
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。
3、需要使用一个算法的不同变体,许多相关的类仅仅是行为有异,算法使用客户不应该知道的数据。
4、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
四、策略模式的优缺点
策略模式的优点:
- 策略模式提供了一种用多个行为替换继承的方法,避免了类的爆炸性增长。
- 策略模式提供了对开放-封闭原则的支持,可以在不修改客户代码的情况下引入新的策略。
- 策略模式提供了管理相关的算法族的办法,使得它们之间可以互相替换。
策略模式的缺点:
- 由于策略模式把每个具体的策略实现都封装在独立的类中,所以会增加系统的复杂度。
- 客户端必须知道所有的策略类,并理解它们的区别,以便选择合适的策略。
总结
策略模式是一种非常实用的设计模式,它可以帮助我们将算法的定义从使用算法的代码中分离出来,使得算法可以独立地变化和扩展。在实际开发中,我们可以根据具体需求灵活地运用策略模式来解决问题。