我正在学习复合设计模式,我不明白当我试图从中添加或删除组件时,我如何才能将每个组件处理为相同的(叶和复合)(否则什么都不会发生)。对我来说,这似乎是一个可怕的设计,因为它违反了继承的规则,将对象处理相同。唯一的办法是从某种程度上区分复合和叶子,并始终意识到我在做什么。但这让我回到原来的问题..。
组件:
public abstract class Equipment {
private String name;
protected Equipment(String name){
this.name = name;
}
public String name(){
return name;
}
public abstract int power();
public abstract double netPrice();
public abstract double discountPrice();
public abstract void add(Equipment equipment);
public abstract void remove(Equipment equipment);
public Iterable<Equipment> createIterator(){
return Collections.emptyList();
}
}复合材料:
public abstract class CompositeEquipment extends Equipment{
private final List<Equipment> elements;
protected CompositeEquipment(String name) {
super(name);
elements = new LinkedList<>();
}
@Override
public double netPrice() {
Iterable<Equipment> iter = createIterator();
double total = 0;
for (Iterator<Equipment> i = iter.iterator(); i.hasNext() ;) {
Equipment next = i.next();
total += next.netPrice();
}
return total;
}
@Override
public Iterable<Equipment> createIterator() {
return elements;
}
@Override
public void remove(Equipment equipment){
elements.remove(equipment);
}
@Override
public void add(Equipment equipment){
elements.add(equipment);
}
}叶:
public class FloppyDisk extends Equipment{
public FloppyDisk(String name) {
super(name);
}
@Override
public int power() {
return 1;
}
@Override
public double netPrice() {
return 3;
}
@Override
public double discountPrice() {
return 2.2;
}
@Override
public void add(Equipment equipment) {
//we will do nothing here because thats the final element of the tree
}
@Override
public void remove(Equipment equipment) {
//we will do nothing here because thats the final element of the tree
}
}我看到的问题:
public void extendTheTree(Equipment equipment){
equipment.add( new CompositeWithLeafs() ); //lets hope it is a Composite not a Leaf!!!
}那么,我应该如何使用这种模式,或者在什么样的场景中使用呢?我看到的唯一解决方案是摆脱叶子的概念,只使用Composits。
发布于 2016-07-10 12:12:27
误解的根源在于,您采用了对叶子有意义的方法和对Component有意义的方法,并将这些方法合并到public abstract class Equipment中,即组件。这样,您就得到了叶子和复合的共同祖先,其中一部分祖先对叶子没有意义。我正在讨论的是add和remove方法,它们对叶子没有意义,因此不应该首先成为组件的一部分。是否应该使用抽象类或接口来表示组件是另一个问题,您可以在这个站点中找到完美的分析。但是事实上,组件应该包含叶子方法和组合方法的交集,这是一组方法,可以在对象上使用,而不知道它是叶子方法还是组合方法。更正式地说,组件应该定义应该由叶子和组合实现的公共接口。如果您这样做,您将发现您永远不可能将add转到Leaf,因为组件接口不应该有这样的方法来覆盖,而Leaf也不应该有这样的方法。无论是好是坏,您只能使用add来实现您所知道的复合功能。
发布于 2022-10-09 19:59:36
来自维基百科:
有两个设计变体用于定义和实现与子组件相关的操作,例如向容器中添加/移除子组件(add(子)/remove(GetChild))和访问子组件(getChild()): 一致性设计:在组件接口中定义了与子相关的操作。这使客户端能够统一地处理叶子和Composite对象。但是类型安全性会丢失,因为客户端可以对叶子对象执行与子相关的操作。 类型安全设计:仅在复合类中定义与子级相关的操作。客户端必须以不同的方式对待叶子和组合对象。但是由于客户端不能对叶子对象执行与子相关的操作,所以获得了类型安全性。 组合设计模式强调的是统一性,而不是类型安全性。
在您的示例中,您选择通过在组件(设备)抽象类中添加与子相关的操作(即添加/删除)来设计一致性,这样您就失去了类型安全性,因为您的客户端可以调用叶子(FloppyDisk)对象上的添加/删除方法。
关于每种设计的优点和缺点的有趣讨论,以及何时选择一种设计而不是另一种设计,都可以找到这里。
https://stackoverflow.com/questions/38290865
复制相似问题