← 返回题目列表

策略模式的优缺点是什么?

高频 中等 第 4 / 26 题 更新于 2026/07/28
策略模式优缺点开闭原则过度设计

简化版

策略模式的优点是隔离算法变化、减少主流程分支、符合开闭原则、便于测试和复用;缺点是类数量增加、调用方或工厂需要知道如何选择策略,策略过多时也会带来管理成本。

详细版

策略模式的优点主要有:

  1. 把不同算法独立封装,职责更清晰;
  2. 新增策略通常不需要修改主流程;
  3. 可以在运行时动态切换策略;
  4. 每个策略可以单独测试;
  5. 避免一个方法里堆满复杂条件分支。

它的缺点也很明显:

  1. 策略类数量会增加;
  2. 需要额外的策略选择机制;
  3. 调用方需要知道业务类型和策略之间的关系;
  4. 策略接口设计不合理时,所有策略都会受影响;
  5. 简单场景使用会显得过度设计。

面试中回答时不要只说优点,要补一句:策略模式适合变化频繁、分支较多的业务点,不适合非常简单且稳定的判断。

完整版教学

一、优点一:隔离变化

策略模式最大的价值是把变化点从主流程中隔离出来。

例如营销优惠规则经常变化,但下单主流程相对稳定。如果把所有优惠规则写在下单方法里,下单方法会被营销规则频繁影响。

策略模式让下单流程只依赖:

discountStrategy.calculate(order);

具体满减、折扣、会员价、新人券都在各自策略里变化。主流程更稳定,也更接近开闭原则。

二、优点二:减少复杂条件分支

复杂 if-else 的问题不是它语法不好,而是它把多个业务规则揉在一起。

策略模式把分支拆成对象后,代码阅读路径会更清晰:

  • 想看会员优惠,就看会员策略;
  • 想看新人优惠,就看新人策略;
  • 想看策略选择,就看策略工厂。

这种结构对后期维护很友好,尤其适合多人协作。

三、优点三:便于测试和复用

每个策略都是独立类,可以单独写单元测试。

例如测试满减策略时,不需要构造整个下单流程,只需要准备订单金额和满减配置,然后断言计算结果。

策略也可以被多个业务场景复用。比如“重量计费策略”既可以用于下单预估运费,也可以用于后台物流结算。

四、缺点一:类数量增加

策略模式会带来更多类:

  • 一个策略接口;
  • 多个具体策略;
  • 一个策略工厂或注册表;
  • 可能还有上下文类。

如果原本只有两种简单判断,并且几乎不变化,拆成策略后反而会让代码显得绕。

所以策略模式不是“看到 if 就上”,而是要看分支复杂度和变化频率。

五、缺点二:策略选择成本

策略模式把算法拆开后,还必须回答:怎么选策略?

选择策略可能依赖:

  • 用户类型;
  • 业务渠道;
  • 订单状态;
  • 配置开关;
  • 灰度规则。

如果选择逻辑本身很复杂,单纯策略工厂可能不够,需要规则引擎、责任链或配置中心配合。

六、缺点三:接口抽象不好会扩散影响

策略接口一旦设计不合理,所有策略都会被迫跟着改。

例如一开始接口是:

BigDecimal calculate(BigDecimal amount);

后来某个策略需要用户等级、商品类型、活动配置,于是不断加参数。最后所有策略都接收一堆自己不用的字段。

更好的做法通常是封装一个上下文参数:

BigDecimal calculate(DiscountContext context);

这样后续扩展字段更稳。

七、扩展收益与选择成本的交换

6 个策略把一个 60 行分支拆成 6 个独立实现,单测可分别覆盖;代价是新增 6 个类和一套 key 映射治理。

benefit: isolated change/test; cost: classes/selection/configuration

这个推演把模式带来的收益和成本放在同一条调用链上。设计评审时既要确认结果正确,也要确认额外层次没有改变原有契约。

八、边界、代价与验证

检查维度应确认的内容
正确性策略模式不是消除复杂度,而是把算法复杂度放到可独立演进和测试的位置。
适用边界规则经常新增且能稳定抽象时收益明显;策略很少且差异只有常量时,配置表可能更简单。
测试证据覆盖正常路径、异常路径、空值或未知类型,并断言调用次数与顺序
运行成本记录额外对象、调用层数、延迟、线程或内存开销,不用模式名称代替测量

模式落地后要用单元测试验证独立职责,用集成测试验证对象装配和真实调用入口。涉及并发、远程或异步时,还要补充竞态、超时、重复执行与资源释放测试。

易错点:策略模式不是消除复杂度,而是把算法复杂度放到可独立演进和测试的位置。

九、常见误区与追问

  • 误区:策略类越多说明设计越符合开闭原则。 类数量不是目标;粒度过细会造成导航和理解成本,仍需稳定、内聚的策略边界。
  • 误区:用了策略模式,系统里就不该再出现任何条件判断。 策略消除的是反复扩张的业务算法分支;选择策略、校验输入和兜底仍可能需要有限判断。
  • 误区:示例代码能运行,就代表模式边界设计正确。 能运行只证明一条路径,仍要检查异常、并发、顺序、生命周期以及新增实现时是否修改稳定代码。
  • 追问:如何控制策略选择成本? 集中注册、校验唯一 key、提供监控和明确兜底,不让选择逻辑散落在调用方。
  • 追问:策略对象可以保存本次请求的可变状态吗? 容器单例策略通常不应保存请求状态,应把订单、用户等数据作为参数传入,否则并发调用会相互污染。
  • 追问:怎样验证这套设计没有改变原有语义? 先做基线行为测试,再对新增层验证返回值、异常类型、调用次数和顺序;性能敏感处还要比较改造前后的量化指标。

十、加强记忆

策略模式的优点是隔离变化、减少分支、方便扩展和测试;缺点是类会变多、策略选择需要额外管理、接口设计不当会拖累所有实现。适合规则多且常变的场景,不适合简单稳定的小判断。