我在headfirst desginpattern一书中读到,decorator模式使用组合关系动态地为对象提供附加功能。但在下面的代码中,我找到了聚合关系,而不是组合关系。
据我所知,合成和聚合的区别在于:
聚合:聚合对象的生命或存在是相互独立的,但一个对象在扮演另一个对象的所有者的角色。
组合:对象的生命或存在依赖于容器对象的存在,没有容器对象,复合对象的存在是没有意义的。
public abstract class Girl {
String description = "no particular";
public String getDescription(){
return description;
}
}
public class AmericanGirl extends Girl {
public AmericanGirl(){
description = "+American";
}
}
public class EuropeanGirl extends Girl {
public EuropeanGirl() {
description = "+European";
}
}
public abstract class GirlDecorator extends Girl {
public abstract String getDescription();
}
public class Science extends GirlDecorator {
private Girl girl;
public Science(Girl g) {
girl = g;
}
@Override
public String getDescription() {
return girl.getDescription() + "+Like Science";
}
public void caltulateStuff() {
System.out.println("scientific calculation!");
}
}
public class Main {
public static void main(String[] args) {
Girl g1 = new AmericanGirl();
System.out.println(g1.getDescription());
Science g2 = new Science(g1);
System.out.println(g2.getDescription());
}
}
有人能指出/解释一下上面的代码是如何遵循组合的吗?
最佳答案
aggregation
和composition
之间的相似性使得它们经常被用作同义词。如果你没有理由做出区分,那就不值得花时间争论到底是什么。如果你有理由的话,你可能已经知道它属于哪一类了。
它们在概念上足够接近你对待它们的方式。如果将关系用作单个单元,则它是一个composition
。如果您与它们相互独立地进行交互,则它是一个aggregation
。
主要的细节在于它的重要性。我能想到的区分两者的主要需要是垃圾收集。在aggregation
中,容器的属性在其容器上下文之外可能仍然有意义。在composition
中,容器的属性应随容器一起销毁。
当观察到与定义相反的对象存在的值时,我相信它可以表示为两者。在某些情况下,您可能只希望销毁容器并保留内容(aggregation
)。然而,如果没有它的委托,它是没有意义的。这在一定程度上定义了inverse composition
。你永远不会想毁掉孩子,留住装修师。
尽管Science
实际上是一个具体的Girl
,但Science.getDescription
的实现会重写基本实现,将请求委托给具体的Girl
。这个实现细节使得Science
girl在没有使用有效的Girl
实现初始化的情况下没有意义。
如果存在本身是没有意义的,那么它通常不是一个aggregation
,而可能是一个composition
。
另外,装饰器通过实现接口而不是继承基类来更清楚地表达。遵循单一责任原则,您可以确定decorator不是主题的实现。