← 返回题目列表

组合模式中的透明式和安全式有什么区别?

高频 中等 第 10 / 25 题 更新于 2026/07/28
组合模式透明式安全式接口设计设计模式

简化版

透明式组合模式把 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。工程里常用安全式,面试时要能说出取舍。