为什么在复合模式中透明度比安全更重要?

Why is transparency valued over safety in the Composite pattern?

我刚刚了解了 Composite pattern。据我了解,其背后的主要思想是统一处理树的边和节点。这意味着结构的 "transparency" 比 "safety" 更有价值,导致我们得到这样的结果:

我理解这个概念,但想不出为了透明度而牺牲安全性的情况会是一个不错的选择。换句话说,在什么情况下我们非常需要透明度以至于我们愿意做出如此严重的牺牲?

在一些关于 Composite 模式的讨论中(包括四人组的原始描述),更准确地说透明度比安全更重要。但是四人组的描述承认权衡,并且 other influential discussions are more pro-safety。无论如何,这是透明度的情况:

安全(声明方法不适用于仅在 Composite 中的 Leaf)有成本:

  • 安全组件树的客户端需要在遍历树时检查每个组件是否是复合组件(可能使用 GoF 书第 168 页所示的外部多态性技术)。树的每个客户端都需要实施此检查,或者,如果在访问者或类似对象中提供检查,则需要处理该复杂性。

  • 组件实现者需要选择每个组件是 Leaf 还是 Composite,如果他们改变他们的选择,则更改他们的代码。

'transparency'(Leaf 和 Composite 的统一性,即在 Component 中声明所有树操作方法)的价值在于将安全成本降至最低。

如果满足以下任一条件,透明度就会变得更有价值:

  • 叶子很少见或根本不存在。例如,在 UI 工具包中,可以将子项添加到任何组件(即使是通常对子项几乎没有用处的组件,如复选框)并期望它们被智能地呈现。因此提供的视觉灵活性可能值得开发人员为 Leafs 付出额外的努力,而组件中的默认实现可能会最大限度地减少这种额外的努力。

  • 树的许多用途不需要区分叶子和复合树。例如,同样在 UI 工具包中,绘图等操作可以通过遍历每个组件的可能为零长度的子级列表来统一处理 Leafs 和 Composites。

  • 相对于程序的其余部分,每个具有子列表的组件的运行时(内存和 CPU)成本较低。

如果上述情况属实,那么统一性会带来更多回报:树的客户使用树时需要做的事情更少,并且这种易用性让客户陷入麻烦的情况很少见。 UI 组件可能经常出现这种情况:树的客户端唯一需要担心某物是否是 Composite 的时间可能是在他们构建(添加)树时,此时是时候他们知道所有具体组件是什么了。

Java Swing 做出了这个选择:JComponent 包括 add 方法。开发人员只需不要将它们与不适合子项的 JComponents 一起使用,这对于许多组件(同样,例如复选框)来说是显而易见的。

如果出现任何相反的情况,那么区分 Leafs 和 Composites 就变得更有价值,并且增加管理安全树的复杂性也变得值得。如果 Leafs 很常见 and/or 树的许多客户端确实需要区分 Leafs 和 Composites,但是类型是 'transparent' 并且不能区分(也许 GoF 应该称这个选择为不透明的而不是比透明),那么客户就更有可能犯错。如果子项列表太昂贵,那么值得让组件实现者选择每个组件是叶组件还是复合组件。