组合设计模式和空覆盖

4
在组合设计模式中,我们以以下UML所示的方式处理层次结构。 Composite design pattern 但是,当您查看上图中的Leaf类时,您会发现它具有addComponent、removeComponent和getChild的空实现,因为这些方法不适用于叶节点。我真正想知道的是,是否有任何方法可以避免实现空/无操作的方法?
更新:好的,我删除了Liskov原则部分,因为现在对我来说已经很清楚了。但仍然不清楚为什么Leaf节点需要强制实现这三个方法,是否有一种方法可以不这样做?我认为还有另一个原则,即子类不应被迫实现不必要的方法。我的主要关注点是叶节点的三个方法的实现,您可以在任何父子结构中考虑这种情况,不一定是组合模式。
1个回答

2
addComponent()removeComponent()getChild() 方法只对 Composite 有意义,因此它们不应在 Component 的 API 中声明。

然而,在 Leaf 中的空实现并不违反 Liskov 替换原则,只要 Leaf 表现出与 Component 定义的行为一致即可。我认为在您的情况下这是正确的。

此外,您可以在 Java Swing 中找到一个很好的组合模式实现示例。请查看java.awt.Componentjava.awt.Container

编辑

我真正需要知道的是,是否有任何方法可以避免实现空的/无操作方法?

Component 设为抽象类而不是接口,并在其中实现 addComponent()removeComponent()getChild() 的空方法。

public abstract class Component {

     public abstract doOperation(); // still need to be implemented by subclasses


     /**
      * Empty stub method. Subclasses may override it.
      */
     public void addComponent(Component comp){
     }

     public void removeComponent(Component comp){
     }

     public Component getChild(int index){
         return null;
     }
}

这意味着Composite将需要公开两个集合(一个用于叶节点,一个用于子组合),或者您需要使用类似访问者模式的东西进行树遍历。 - heinrichj
使用复合模式时,您希望将元素集合处理为一个元素本身。因此,如果在Composite对象上调用doOperation,它将只是迭代所有子元素并调用doOperation()。它不需要知道子元素是否是复合的。 - René Link
@heinrichj 不过,你当然可以将访问者模式与组合模式结合使用。我只是想说这并非绝对必要。 - René Link
@RenéLink 好的,我更新了我的问题。你有关于那个的任何东西吗? - xmaestro
@RenéLink 是的,我认为这正是我所希望的 :) - xmaestro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接