关键词:设计模式 / 策略模式 / 面向对象 / 代码结构 / 工程思维
一、前言
作为一名计算机专业的学生,于大二本科初学设计模式课程之时,我曾对其充满向往和好奇。
“能轻松写出使用工厂、单例、观察者的代码并运用到实际业务开发中,是不是就离架构师不远了?”
然而,深入学习后我开始有一个疑问:
设计模式到底是“必须掌握的套路”,还是“有选择使用的工具”?
下面我将以策略模式为例,从动机、结构、优点再到误用的典型场景,逐步剖析它在开发中真正的价值,并分享我在学习过程中的一些反思和心得。
二、策略模式:定义与结构
策略模式的核心目的是封装算法的变化,将行为抽象出来,使得算法之间可以自由切换且互不影响。
模式结构
public interface Strategy {
void execute();
}
public class StrategyA implements Strategy {
public void execute() {
System.out.println("执行策略A");
}
}
public class StrategyB implements Strategy {
public void execute() {
System.out.println("执行策略B");
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void run() {
strategy.execute();
}
}
调用方式:
Context context = new Context(new StrategyA());
context.run();
结构非常清晰:抽象策略接口、若干具体策略类、一个使用策略的上下文类。
三、模拟业务:会员折扣系统
假设我们正在实现一个“会员折扣”系统,不同等级的用户有不同的折扣规则:
- 普通用户:无折扣
- VIP 用户:9 折
- 超级 VIP:8 折
一种“使用策略模式”的写法如下:
public interface DiscountStrategy {
BigDecimal calculate(BigDecimal price);
}
public class NormalUserStrategy implements DiscountStrategy {
public BigDecimal calculate(BigDecimal price) {
return price;
}
}
public class VipUserStrategy implements DiscountStrategy {
public BigDecimal calculate(BigDecimal price) {
return price.multiply(BigDecimal.valueOf(0.9));
}
}
public class SuperVipUserStrategy implements DiscountStrategy {
public BigDecimal calculate(BigDecimal price) {
return price.multiply(BigDecimal.valueOf(0.8));
}
}
通过配置 Map<String, DiscountStrategy>,我们就可以根据用户等级获取对应策略并计算价格。
四、看似合理,但真的是“最佳实践”吗?
通过模拟开发场景,我逐渐意识到:
策略模式的使用,并不总是带来正收益。
以下是策略模式在这个案例中可能引发的问题:
1. 策略逻辑过于简单
三种策略只有一行代码,抽象出三个类显得非常冗余。为了解耦,反而引入了复杂性。
2. 策略扩展性并不强
假设系统一年最多改一次折扣策略,引入扩展性强的设计模式显得“小题大做”。
3. 维护成本上升
多人协作开发时,过度抽象的结构反而降低了代码可读性,不如用清晰的 switch 更直观。
五、那应该怎么判断是否使用策略模式?
我总结出以下判断标准,供大家在面对策略型场景时思考是否引入设计模式:
| 判断维度 | 使用策略模式 | 不使用策略模式 |
|---|---|---|
| 策略种类 | ≥ 3 类,差异明显 | ≤ 2 类,逻辑简单 |
| 策略变动频率 | 频繁新增或变更 | 几乎固定 |
| 策略结构复杂度 | 结构差异较大 | 实现逻辑只有一两行 |
| 可维护性 | 抽象更易管理 | 代码越抽象越难维护 |
六、更轻量的实现方式?
当策略较少、逻辑简单时,使用 Java switch 或 Map 映射就足够优雅了:
BigDecimal discount = switch (user.getLevel()) {
case "NORMAL" -> price;
case "VIP" -> price.multiply(BigDecimal.valueOf(0.9));
case "SUPER_VIP" -> price.multiply(BigDecimal.valueOf(0.8));
default -> price;
};
对比策略模式的类结构,这种写法在“适当的复杂度下”更容易理解与维护。
七、我对设计模式的学习反思
在阅读《Head First 设计模式》《大话设计模式》这类书籍时,我曾经希望每一个场景都能套一个模式。但渐渐明白:
- 设计模式是为了解决“变化”带来的不稳定,而不是追求架构美感。
- 不要为了设计模式而设计,而是为了“业务演化”准备好结构。
- 没有银弹,也没有模式是永远的答案。
八、总结
策略模式是一种经典的行为型模式,适用于“算法族类问题”的场景。但在应用时应权衡其带来的抽象与复杂度。
合理使用策略模式的关键不在于掌握结构,而在于判断“是否真的需要它”。