一、策略模式介绍
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每一种算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的上下文对象。策略模式涉及到三个主要角色:
策略接口(Strategy Interface):定义了一个公共接口,所有的算法或行为以这个接口为准。环境角色使用这个接口来调用具体的算法。
具体策略类(Concrete Strategies):实现了策略接口的类。具体策略类封装了具体的算法或行为,并负责具体的计算过程。
环境类(Context):接受客户的请求,随后把请求委托给某一个策略类。环境类会维护对策略对象的引用,并可在运行时动态地改变具体的策略。这个类一般会有一个成员变量来保存对策略对象的引用,还有一个成员方法来设置环境对象的策略。
策略模式的优点
- 算法自由切换:策略模式使得算法可以在不影响到客户端的情况下变化。
- 避免使用多重条件判断:将条件判断语句转移到了具体的策略类中进行,从而避免了多重条件语句。
- 扩展性良好:当增加一个新的算法时,不需要修改原来已经写好的代码,只需要添加一个新的策略类即可。
策略模式的缺点
- 策略类会增多:每增加一个策略,就需要增加一个策略类,这样会导致系统中类的个数大量增加。
- 客户端必须知道所有的策略类:客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
适用场景
- 当一个系统有许多许多类,它们之间的区别仅在于它们的行为,而这些行为要使用一个系列的算法来表示时。
- 当这些算法需要自由地互换为系统的行为时(如排序算法)。
- 当算法需要隐藏,或者要访问算法的接口而不需要知道算法是如何实现的时候。
- 当一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现时,可以使用策略模式将各种算法封装起来。
策略模式是一种非常灵活和强大的设计模式,它可以让我们在运行时动态地改变对象的行为,从而达到更好的代码复用和更高的可维护性。
二、策略模式实现例子
首先,我们定义一个策略接口(Strategy Interface):
public interface Strategy {
void execute();
}
然后,我们创建几个实现了这个接口的具体策略类:
public class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("Executing strategy A");
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("Executing strategy B");
}
}
// 可以根据需要添加更多的具体策略类
接下来,我们创建环境类(Context),它接受客户端的请求,并将请求委托给某个具体的策略类执行:
public class Context {
private Strategy strategy;
// 构造函数,用于设置具体的策略
public Context(Strategy strategy) {
this.strategy = strategy;
}
// 上下文接口,用于执行策略
public void executeStrategy() {
strategy.execute();
}
// 允许在运行时更改策略
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
最后,我们创建一个客户端来测试这个策略模式:
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategyA());
context.executeStrategy(); // 输出:Executing strategy A
// 更改策略
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy(); // 输出:Executing strategy B
}
}
在这个例子中,Context类通过其构造函数接受一个Strategy类型的对象作为参数,这个对象可以是任何实现了Strategy接口的具体策略类实例。Context类内部有一个executeStrategy方法,它调用了当前策略对象的execute方法。这样,当客户端需要改变算法或行为时,它只需要通过setStrategy方法更换Context对象中的策略对象即可,而不需要修改Context类本身或其他使用Context类的代码。
正常情况下,对于选择哪种策略,要设计一个策略选择器,根据上下文的条件,给出一个策略,然后执行该策略,这样可以减少客户端调用的认知负载,策略模式也是我最喜欢用的模式之一。
如果觉得不错,记得点赞收藏~