首页/开发/代码质量与评审速查/开闭原则 OCP(Open-Closed Principle)
设计原则与模式62 条

开闭原则 OCP(Open-Closed Principle)

软件实体应对外扩展开放、对修改关闭(Bertrand Meyer 提出):新增行为靠扩展(新实现、新分支集中于注册点),而不是改动被反复触碰的旧逻辑。

开闭原则讲什么

开闭原则由 Bertrand Meyer 提出:软件实体应当对扩展开放、对修改关闭。落到工程实践里,就是在需求增加新类型时尽量只新增代码(新实现、新配置项),而不是反复修改同一条判断链路。它不意味着永不修改——扩展点本身仍会演进,只是把变化集中到少量稳定接口上。

基本信息

提出者Bertrand Meyer(1988 年)
落地手段策略模式、多态、插件注册、配置驱动
前置条件先稳定变化点:确认哪些维度会持续增加
常见误区把开闭原则理解为「代码永远不改」

什么时候值得引入扩展点

  • 同一段分支判断已经因为新类型改过两次以上。
  • 分支内部逻辑较长,且各分支之间几乎没有共享代码。
  • 新增类型的时间点可预期(如新支付渠道、新导出格式)。
  • 分支的取舍需要由配置或运行时决定,而不是编译期固定。
  • 改动这段代码的风险较高,希望把变化限制在新文件里。

扩展点形态

扩展点形态
// 新增支付方式:只新增实现类并注册,不改调用链
interface PaymentMethod { PayResult pay(Order o); }
class Alipay implements PaymentMethod { ... }
class WechatPay implements PaymentMethod { ... }
// 调用侧通过注册表或依赖注入按名称取实现

改分支与加扩展点对比

维度持续改分支扩展点
新增类型改动集中在同一处,冲突与风险叠加新增实现文件,改动隔离
可测试性需要构造大量分支条件每个实现可单独测试
理解成本一个函数里读所有类型需要按接口追踪实现位置
适用前提类型少且稳定类型会持续增加
开闭原则不是「永不修改」:扩展点本身仍会演进,只是把变化集中到少量稳定的接口上。
先确认变化方向再抽象:在只有一种实现的场景里预先设计插件机制,通常只是在增加认知成本。
扩展点要在调用侧集中注册:实现分散在多个文件中查找,会让「新类型」这件事重新变得昂贵。

易错点

  • 为每个改动都硬找扩展点:抽象层暴增,简单需求被复杂化。
  • 只加分支不改结构:判断越堆越长,仍然是修改驱动。
  • 把配置当成万能扩展点:表达式与开关越写越复杂,最终无人敢改。
  • 扩展点没有稳定契约:每次新增实现都要回头改接口,变化并未隔离。

数据来源与参考

  • Bertrand Meyer《Object-Oriented Software Construction》(1988)OCP 原始表述
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌