是什么
移除中间人(Remove Middle Man)处理转发过多的情形:当一个类的方法大多只是把调用原样转给另一个对象时,中间层已经没有独立价值,让调用方直接与真实对象交互即可。它与隐藏委托互为反向操作——封装与暴露之间的取舍取决于中间层是否还在承担职责。动手前的关键动作是确认中间人没有隐藏的横切职责。
识别与前置检查
| 信号 | 中间类的方法大多只有一行转发 |
|---|---|
| 前置检查 | 是否承担校验、埋点、权限、缓存等横切职责 |
| 做法 | 暴露真实对象引用,删除纯转发方法 |
| 反向操作 | 隐藏委托:调用链过长且中间层需要收拢复杂度时再包一层 |
典型使用场景
- 为了封装而层层包装:三层都是转发,调用链变长,删除多余的中间层
- 字段访问转发:为内部集合提供了完整的一组转发方法,不如直接暴露只读视图
- 包装类只剩转调:原实现细节已稳定,包装带来的灵活性没有实际用途
- 历史遗留的委托层:当初为隔离外部库而建,该外部库已经被替换为可控实现
- 测试替身难写:中间层太多导致需要逐层打桩,移除后可以直接替换真实依赖
核实要点
核实要点
// 纯转发:中间层没有增加任何职责
void pay() { ledger.pay(); }
// 有职责:审计与校验发生在这里,不能直接删掉
void pay() {
audit.log(); // 记录操作
ledger.pay();
}保留还是移除
| 中间层承担的事 | 判断 | 理由 |
|---|---|---|
| 只做方法转发 | 移除 | 没有独立职责,只是增加调用层级 |
| 参数校验与规范化 | 保留 | 调用方依赖这层保证,删掉会改变契约 |
| 权限判定 | 保留 | 安全职责分散到调用方极易出错 |
| 埋点与审计 | 保留或显式化 | 删除会导致可观测性或合规记录丢失 |
| 协议转换 | 保留 | 转换逻辑有独立变化轴,属于适配器职责 |
| 缓存与批处理 | 保留 | 属于性能策略,调用方不应自行实现 |
移除后直接暴露内部对象,调用方可能顺手修改内部状态:配合提供只读视图或不可变集合,避免把封装问题转化成数据一致性问题。
移除中间人常与内联类、隐藏委托配合使用:中间层数量多时,先逐层判断职责,再决定移除还是保留,不必一次改完所有层级。
落地检查清单
- 删除前逐条核对被删方法是否有隐含职责
- 暴露对象时提供只读视图,不直接交出可变内部结构
- 调用点更新后跑一遍涉及权限与审计的测试
- 文档中记录移除原因,避免后来者又加回中间层