文章目录
前言
学习设计模式不仅仅是炫技,还可以让你 在看各种代码时如鱼得水。碰到一些典型的设计模式,还会惊讶于Coder的设计。
今天来分享设计模式中的策略模式,也是最近在实习中看到的。
其实策略模式在项目中的应用很多,封装不同的算法,然后只需要调用即可,这样即使你不会设置一些算法(策略),但是你可以拿到别人设计好的策略开箱即用。
什么是策略模式?
就像之前说的,策略模式会定义一系列算法,或者叫做策略 - Strategy。每个算法会独立封装在特定的类中,使用哪个策略,直接调用替换即可。注意:替换的过程是在运行中动态完成的,不需要修改客户端代码。
- 策略模式的组成部分
- 抽象策略(Strategy):定义了所有策略类必须实现的接口或抽象类。
- 具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含具体的算法实现。
- 环境(Context):维护一个对策略对象的引用,并通过该引用调用策略。
一般我们的具体策略可以通过工厂模式来生产:策略对象。我们想要调用什么策略,就从工厂拿哪个策略即可。
谁去调用这个策略呢?可以维护一个Map。key就是我们的触发策略条件,value就是我们具体的策略;
接下来我们来看一个代码具体分析策略模式的作用:
策略模式核心实践
java
// 抽象策略接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
// 具体策略类A
public class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
// 具体策略类B
public class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
// 环境类
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
// 测试策略模式
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
}
}
我们定义了两个策略,加策略 和 减策略。
Context是我们的环境,环境不知道具体调用了哪个策略,因为环境只配置了抽象策略类的引用。
具体调用哪个策略,由我们来决定,比如前端传入 +
,那么我可以从Map中匹配 +
对应的策略就是OperationAdd,此时我把OperationAdd添加到环境中,直接让环境调用抽象策略类,这样就选择到了我们的具体策略类的重写实现。
这就是策略模式的主要使用方式,
策略模式的优点
- 算法切换自由:可以在运行时根据需要切换不同的算法,而无需修改客户端代码。这使得系统更加灵活和可扩展。
- 避免多重条件判断:通过将算法封装在独立的策略类中,消除了复杂的条件语句(如 if-else 或 switch-case),使代码更加清晰和易于维护。
- 扩展性好:新增算法只需新增一个策略类,无需修改现有代码。这符合开闭原则(Open/Closed Principle),即对扩展开放,对修改关闭。
- 提高代码复用性 :不同的策略类可以在不同的环境中复用,避免了代码重复。
- 比如我们很多策略有重复的代码 ,我们就可以把相同的行为抽象成同一个,减少重复代码。
- 简化单元测试 :每个策略类都可以独立测试,确保每个算法的正确性。同时也做到了业务逻辑与算法分离。
策略模式的缺点
- 如果你本来就用不到多少策略,算法不经常改变,这样你就没必要使用策略模式,只会增加代码的复杂度;
- 客户端必须知道不同策略的不同 - 我们需要选择合适的策略;