gpt4 book ai didi

java - 使用复合类 : how a client can determine whether it is composite

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:01:57 25 4
gpt4 key购买 nike

我知道有一个类似的问题 here .它考虑了比我在这里的问题更通用的类特定行为问题。

考虑以下复合模式的简单实现:

interface Item {
int getWeight();
}

class SimpleItem implements Item {
private int weight;
public int getWeight() {
return weight;
}
}

class Container implements Item {
private List<Item> items;
private int weight;
public void add(Item item) {
items.add(item);
}
public int getWeight() {
return weight + items.stream().mapToInt(Item::getWeight).sum();
}
}

现在考虑 Item 的用户如何确定它是否是一个容器。例如,Container pushAdd 中需要一个方法,该方法将一个项目向下推到一个没有容器的容器中。容器只知道项目,它不知道这些项目是容器还是简单项目或其他实现项目的类。

存在三种可能的解决方案:

1.使用和类型转换的实例

public void pushAdd(Item item) {
Optional<Container> childContainer = items.stream()
.filter(item instanceof Container)
.map(item -> (Container)item)
.findAny();
if (childContainer.isPresent()) {
childContainer.get().pushAdd(item);
} else {
add(item);
}
}

2。实现 is/as 方法

public pushAdd(Item item) {
Optional<Container> childContainer = items.stream()
.filter(Item::isContainer)
.map(Item::asContainer);
....
}

3。访问者模式(我省略了简单的 accept 实现)。

interface ItemVisitor {
default void visit(SimpleItem simpleItem) { throw ...}
default void visit(Container container) { throw ... };
}

public pushAdd(Item item) {
Optional<Container> childContainer = ... (using instanceOf);
if (childContainer.isPresent()) {
childContainer.get().accept(new ItemVisitor(item) {
void visit(Container container) {
container.pushAdd(item);
}
};
} else {
add(item);
}
}

第一个是邪恶的,因为它使用了 instanceof 和转换。第二个是邪恶的,因为它将 Container 的知识强加到 Item 中——当创建了 item 的其他子类时,情况会变得更糟。第三个不会帮助您知道在调用访问者之前是否可以添加到项目中。您可以捕获异常,但对我来说这似乎是对异常的滥用:最好有一种在访问前进行检查的方法。

所以我的问题是:是否可以使用另一种模式来避免转换和 instanceof,而不必将子类的知识推到层次结构中?

最佳答案

当我说访问者模式在 Java 中并不流行时,我想我代表了所有 Java 人。所以上面可以这样实现(我将在这里使用接口(interface),因为根据我的经验,它们更灵活):

interface Item { /* methods omitted */ }

interface SimpleItem extends Item { /* methods omitted */ }

interface ContainerItem extends Item { /* methods omitted */ }

// telling clients that this can throw an exception or not
// here is a whole different design question :)
interface ItemVisitor { void visit(Item i) /* throws Exception */; }

class MyVisitor implements ItemVisitor {
void visit(Item i) {
if (i instanceof SimpleItem) {
// handle simple items
} else if (i instanceof ContainerItem) {
// handle containers using container specific methods
} else {
// either throw or ignore, depending on the specifications
}
}
}

instanceof 的成本在最新的 JVM 上非常低,所以我不会太担心,除非你能证明传统的访问者要快得多。

代码的可读性和可维护性可以说是相同的,只有一些差异。首先,如果将新界面添加到层次结构中,不会修改现有访问者,则不需要更改这些访问者。另一方面,更容易忽略确实需要更改的访问者(尤其是在您无法控制的客户端代码中),因为访问者没有明确要求客户端这样做,但是,嘿,这就是维护代码的本质和需要访问的设计的一般缺点。

这种模式的另一个优点是不需要访问的客户端不需要担心它(没有 accept 方法),即更短的学习曲线。

最后,我认为这种模式更接近于“纯粹的”OOD,因为接口(interface)层次结构不包含虚假方法(visitcanAddItems 等。 ), 即有 no "tags"各种各样的。

关于java - 使用复合类 : how a client can determine whether it is composite,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27853657/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com