组合模式中的透明式和安全式有什么区别?
简化版
透明式组合模式把 add/remove/getChild 等子节点管理方法放在 Component 接口里,客户端使用最统一,但叶子节点也会暴露不支持的方法;安全式组合模式只让 Composite 提供子节点管理方法,类型更安全,但客户端不能完全通过 Component 管理树。
详细版
两种写法对比:
| 写法 | 子节点管理方法放哪 | 优点 | 缺点 |
|---|---|---|---|
| 透明式 | Component 接口 | 客户端统一 | Leaf 也暴露无意义方法 |
| 安全式 | Composite 类 | 类型更安全 | 客户端需要知道 Composite |
透明式:
interface Component {
void add(Component child);
void remove(Component child);
void operation();
}
安全式:
interface Component {
void operation();
}
class Composite implements Component {
void add(Component child) {}
}
工程里更常用安全式,因为它不让叶子节点暴露无意义方法。
完整版教学
一、透明式组合模式
透明式把所有方法都放到统一接口里:
interface Component {
void add(Component child);
void remove(Component child);
void operation();
}
这样客户端只依赖 Component 就能做所有事情。
问题是叶子节点也必须实现 add() 和 remove()。
二、透明式的问题
叶子节点没有子节点。
如果它实现:
public void add(Component child) {
throw new UnsupportedOperationException();
}
客户端调用时可能运行期才发现错误。
这会让接口语义不够干净。
三、安全式组合模式
安全式只把公共行为放到 Component:
interface Component {
void operation();
}
子节点管理方法只放到 Composite:
class Composite implements Component {
private List<Component> children = new ArrayList<>();
void add(Component child) {
children.add(child);
}
}
这样叶子节点不需要实现无意义方法。
四、安全式的问题
安全式的缺点是客户端如果要构建树,必须知道某个对象是不是 Composite。
例如:
Composite menu = new MenuGroup("系统管理");
menu.add(new MenuItem("用户管理"));
构建阶段依赖具体组合类,但使用阶段仍然可以依赖 Component。
五、怎么选择
如果业务更重视统一接口,且调用方能接受不支持操作,可以选透明式。
如果业务更重视类型安全和接口语义,通常选安全式。
大多数工程场景更推荐安全式:
- 叶子不暴露无意义方法;
- 编译期语义更清晰;
- 运行期异常更少。
六、常见误区与追问
透明式与安全式的取舍集中在子节点管理接口放在哪里。透明式让1个 Component 同时声明 add/remove/operation,客户端完全统一,但 Leaf 只能抛异常或空实现;安全式只让 Composite 声明管理方法,编译期更安全,却需要客户端知道容器类型。选择应基于“统一管理”是否比误调用风险更重要。
| 检查维度 | 判定依据 |
|---|---|
| 透明式 | 统一程度高,叶子可能暴露无效方法 |
| 安全式 | 类型安全高,管理时需区分容器 |
记忆钩子:透明式把选择留到运行期,安全式把错误挡在编译期。
- 误区:透明式一定优于安全式。 公共接口被无效方法污染时,运行期异常可能比统一调用更糟。
- 追问:Leaf 的 add 应空实现还是抛异常? 若采用透明式,抛出明确异常通常比静默忽略更易发现错误。
- 误区:安全式不属于组合模式。 它仍统一核心业务操作,只把结构管理能力留给 Composite。
- 追问:只读树适合哪种设计? 可只在 Component 暴露遍历能力,把修改操作放入独立构建接口。
- 追问:如何从 API 看出选择结果? 检查 add/remove 位于公共 Component 还是仅位于 Composite。
七、加强记忆
透明式追求“接口最统一”,代价是叶子也有 add/remove;安全式追求“类型更安全”,代价是构建树时要知道 Composite。工程里常用安全式,面试时要能说出取舍。