java - 如何处理复合模式中的添加、删除功能?

标签 java oop design-patterns composite

复合模式对于处理部分-整体层次结构非常有用。它有一个Component 接口(interface)。 LeafComposite 都提供 Component 接口(interface)的实现。

Add(Component c)Remove(Component c)GetChild(intposition) 方法在 类?

我可以让方法不执行任何操作,或者抛出异常,例如:OperationNotSuportedByLeafException但是这样做会打破里氏替换原则。处理这些方法的最佳方法是什么?

编辑:另一种方法是在 Composite 中移动这些方法。它将是暴露的最顶层接口(interface),即组件。当需要调用 addremove 操作时,移动 Composite 中的方法将需要显式转换,这又违背了良好的设计原则。

enter image description here

最佳答案

当然取决于您的设计目标是什么。如果您的目标是树/图应该在任何时间点都可以修改,那么叶子实际上可以成为父节点。在这种情况下,可以在组件中定义与层次结构相关的方法。

另一种方法(虽然我不知道这是否适用于您的用例)是使用以下两个想法:

  • 使结构不可变
  • 将结构与功能分开

通过使结构不可变,我们可以将所有图构造推送到构造函数。这样我们就回避了您提到的类型转换问题,并且也使整个事情更容易推理。

通过将结构与功能分离,我们根本不需要向客户端发布结构信息,而是提供我们想要提供的功能。这样我们就可以保留 Liskov、Demeter 和其他 OO 的东西。

它是这样的:

public interface Node {
    // Here we offer the "functionality", but we don't
    // publish the "structure". This is made-up, I
    // don't know your use-case.
    void process(Consumer<Payload> payloadConsumer);
}

public class Leaf implements Node {
    private Payload payload;

    public Lead(Payload payload) {
        this.payload = payload;
    }

    @Override
    public void process(Consumer<Payload> payloadConsumer) {
        payloadConsumer.accept(payload);
    }
}

public class ParentNode implements Node {
    private List<Node> children;

    public ParentNode(Node... children) {
        this.children = asList(children);
    }

    // Here we implement the processing recursively.
    // All children can respond according to their semantics,
    // instead of assuming any structure beyond what we know.
    @Override
    public void process(Consumer<Payload> payloadConsumer) {
       children.forEach(child -> child.process(payloadConsumer));
    }
}

当然,您可以根据您想要表示的逻辑类型来定义自己的Node类型。您可以定义多个操作,而不仅仅是我编写的一个 process() 方法。然后你可以像这样将所有这些连接在一起:

Node graph = new ParentNode(
   new ParentNode(new Leaf(p1), new Leaf(p2)),
   new SpecialLeaf(a, b, c) // Whatever
);

关于java - 如何处理复合模式中的添加、删除功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37576120/

相关文章:

C# 将 Foreach 值转换为其属性之一

iOS/AVFoundation : Design pattern for asynch handlers when turning arrays of images into tracks and then into a single video?

java - Struts 2中的ActionContext对于当前请求来说是唯一的吗?

java - 如何在Java/JSP中使用jQuery网格插件?

java - 如果我在更新期间将 json 中的空 id 传递给子实体,为什么 Hibernate 会插入新记录

java - 如何对多个耦合对象使用泛型?

design-patterns - 对象在单击时行为不同的设计模式,具体取决于全局状态

java - 为什么在某些情况下我们必须将 Immutable 转换为 Pair?

class - 在Lua中,每个 "object"都必须有自己的方法副本吗?

javascript - Javascript 原型(prototype)设计错​​误 "Class"- 不是函数且 undefined variable