设计模式-分与合

23种设计模式的分与合:先拆开,再组装

上一篇把 23 个模式做成了选型地图,这一篇换一个更本质的视角:设计模式没有创造新语法,它做的核心动作只有两个——把耦合拆开,把职责合起来。掌握这条主线,比背住 23 个类图更管用。

一、先建立两个动作

所有设计模式都可以被拆成两个动作。

1. 分:把变化从稳定代码里拿走

一段代码之所以越来越难改,通常不是因为功能多,而是因为多个变化原因挤在同一个类或同一个方法里。

“分”就是把它们拆开:

  • 把创建逻辑从业务逻辑中分出去;
  • 把算法从调用方中分出去;
  • 把状态判断从各个方法中分出去;
  • 把访问控制从真实业务中分出去;
  • 把多个对象之间的网状通信拆成单向通信。

2. 合:用抽象把分散的角色重新组织起来

拆开之后,如果只是把一个大类变成一堆互相引用的小类,代码并不会自动变好。模式的另一半价值,在于用一个稳定的抽象把它们重新组合起来。

“合”的常见手段有:

  • 统一接口;
  • 统一入口;
  • 统一容器或上下文;
  • 统一消息总线或协调者;
  • 统一对象结构或树形结构。

所以设计模式的完整动作通常是:先分后合,分是为了隔离变化,合是为了保持稳定协作。

二、23个模式各自的“分”与“合”

下面这张表把每个模式都拆成“先分了什么”和“又合成了什么”。你会发现,很少有模式只做其中一件事。

序号类型模式先分:把什么拆出去再合:用什么把角色重新组织
1创建型单例模式把实例创建与业务使用分开用全局唯一入口收敛所有访问
2创建型工厂模式把“创建谁”从业务调用中分出用工厂接口或注册表统一创建入口
3创建型抽象工厂模式把成套产品的创建逻辑拆成产品族用抽象工厂约束一组对象必须配套
4创建型建造者模式把构造步骤从目标对象中拆出用 Builder 链把分散步骤合成为完整对象
5创建型原型模式把“从零创建”替换成“复制已有对象”用统一 clone 语义复用一个可靠样板
6结构型适配器模式把内部接口与外部 SDK 的直接绑定分开用翻译层把新旧接口接合
7结构型桥接模式把抽象与实现两个变化维度拆开用组合关系把它们重新连接
8结构型组合模式把叶子与容器的处理逻辑从客户端分走用统一节点接口合成树形结构
9结构型装饰器模式把横切能力从核心逻辑中拆出用同接口的包装链叠加能力
10结构型外观模式把客户端与多个子系统的耦合拆开用单一门面收敛复杂协调过程
11结构型享元模式把可变状态与不变状态分开用共享池把重复对象合成共享样本
12结构型代理模式把访问控制从真实业务中拆出用同接口代理统一承接访问
13行为型模板方法模式把可变步骤从固定流程中分出用抽象模板把流程骨架固定下来
14行为型策略模式把算法分支从业务判断中拆出用上下文与策略接口统一选择和执行
15行为型观察者模式把通知接收方从被观察者中拆出用订阅关系合成一对多通知
16行为型责任链模式把层层 if-else 拆成独立处理节点用链式指针合成一条处理路径
17行为型命令模式把调用者与接收者拆开用命令对象把动作、排队和撤销统一起来
18行为型解释器模式把规则从硬编码中拆出用表达式对象树合成语法解释过程
19行为型迭代器模式把遍历方式从容器内部拆出用统一迭代器接口合成遍历过程
20行为型中介者模式把对象之间的网状依赖拆开用中介者把通信合成为星型结构
21行为型备忘录模式把状态快照从对象外部操作中拆出用备忘录对象统一保存和恢复状态
22行为型状态模式把状态判断从每个方法中拆出用状态对象合成对象的状态机
23行为型访问者模式把新增操作从稳定元素中拆出用访问者接口统一承载一组操作

三、分与合不是对立,而是同一枚硬币的两面

很多人会把“拆分”和“整合”理解成相反方向,但设计模式里的分与合通常是连续发生的。

1. 策略模式:先分算法,再合选择

满减、折扣、新人价本来是一个大 if-else。策略模式先把它拆成多个策略类,然后引入 DiscountContext 把“策略查找、持有、执行”重新合起来。

如果没有第二步的“合”,客户端就要自己知道所有策略类,拆得越细越难用。

2. 组合模式:先分叶子与容器,再合成统一节点

文件系统中有文件也有目录。如果客户端分别处理 FileDirectory,代码会出现大量类型判断。组合模式先承认叶子与容器不同,再用统一的 Component 接口把它们合起来,让客户端只看到“节点”。

3. 中介者模式:先拆网状依赖,再合成中心协调

库存、支付、物流、积分、通知互相直接调用时,关系是一张网。中介者模式先切断参与者之间的直接依赖,再把它们的通信全部合到 Mediator 上。拆的是连接,合的是协作规则。

4. 访问者模式:先分操作,再合到访问者接口

文本、图片、表格的数据结构很稳定,但统计、导出、预览这些操作不断新增。访问者模式先让元素不再自己实现所有操作,再把同一批操作合到一个访问者对象里。分的是“操作责任”,合的是“操作入口”。

四、真实系统里,模式往往需要组合使用

单个模式解决单个问题,但一个业务流程往往同时需要“分”和“合”多次。以下组合在工程中最常见。

1. 工厂 + 策略 + 模板方法

工厂负责把策略对象创建出来,策略负责选择算法,模板方法负责固定整个流程骨架。

比如订单结算:

  • 工厂:根据优惠类型创建策略;
  • 策略:替换满减、折扣、会员价;
  • 模板方法:固定“校验订单 → 计算金额 → 记录流水”的流程。

这是一个很典型的“先分算法、再合入口、最后固定流程”的组合。

2. 观察者 + 中介者

观察者适合“一对多通知”,但当参与者之间还有复杂的先后顺序时,观察者容易变成隐式依赖网。

更稳妥的用法是:

  • 观察者负责广播“发生了什么”;
  • 中介者负责编排“接下来谁来做”。

前者解决通知解耦,后者解决流程集中。

3. 组合 + 迭代器 + 访问者

树形结构里,组合负责统一节点,迭代器负责统一遍历,访问者负责把统计、导出等操作从节点中拆出。

例如报表树:

  • 组合:让文本、图片、表格都有统一的 accept
  • 迭代器:让客户端不关心树的内部存储方式;
  • 访问者:新增导出、统计时不再修改节点类。

4. 建造者 + 工厂

建造者解决“复杂对象怎么一步步创建”,工厂解决“应该选择哪个建造者或产品”。一个负责过程的组织,一个负责入口的收敛,经常配合使用。

五、用“分与合”检查一段代码

做代码评审时,可以用四个问题替代“这里该用什么模式”:

  1. 哪里最容易变? 这个变化现在被写在什么类或什么方法里?
  2. 是否已经把变化拆出去了? 如果新增一种算法、状态、渠道或操作,是否需要改动稳定代码?
  3. 拆完之后有没有一个稳定接口把角色合起来? 如果拆成一堆互相了解具体类的小类,说明只有“分”,没有“合”。
  4. 这个“合”会不会成为新的上帝对象? 门面、中介者、上下文如果承载太多,就是过度收敛,需要再次分。

小结

23 种设计模式看似各有套路,本质都在做同一件事:把容易变化的部分分出去,把必须稳定协作的部分合起来。

只分不合,系统会碎成高耦合的小类;只合不分,系统会退化成巨大的上帝类。真正的设计能力,是在“什么时候该分、分到哪一层”和“什么时候该合、用什么抽象来合”之间做判断。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值