我在HeadFirst DesginPattern书中读到,装饰器模式使用组合关系动态地为对象提供附加功能。但是在下面的代码中我找到了聚合关系而不是组合。
据我所知,组合和聚合之间的区别是:
聚合:聚合对象的生命或存在是相互独立的,但是一个对象扮演另一个对象的所有者的角色。
组合:复合对象的生命或存在依赖于容器对象的存在,没有容器对象,复合对象的存在是没有意义的。
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());
}
}
有人可以指出/解释上面的代码是如何遵循组合的吗?
答案 0 :(得分:1)
aggregation
和 composition
之间的相似性使它们经常被用作同义词。国际海事组织如果你没有理由进行区分,那么它的实际辩论时间是不值得的。如果你确实有理由,你可能已经知道它属于哪个。
他们在概念上足够接近他们是如何对待他们的。如果您将关系用作单个单元,则它是 composition
。如果您彼此独立地互动,那么它就是 aggregation
。
主要细节在于它的重要性。我能想到的两者之间的区别主要是垃圾收集。在 aggregation
中,容器的属性在其容器上下文之外可能仍然有意义。在 composition
中,容器的属性应该与容器一起销毁。
当观察到与定义相反的对象存在的值时,我相信它可以表示为两者。在某些情况下,您可能希望仅销毁容器并保留内容( aggregation
)。但是,如果没有它的代表,它就毫无意义。这定义了一些 inverse composition
。你永远不想破坏孩子并保留装饰。
虽然Science
实际上是具体的Girl
,但Science.getDescription
的实现会覆盖基本实现,以将请求委托给具体的Girl
。此实现细节使Science
女孩没有用有效的Girl
实现进行初始化而毫无意义。
如果存在本身没有意义,那么它通常不是 aggregation
,而可能是 composition
。
另外,通过实现接口而不是继承基类,可以更清楚地表达装饰器。坚持单一责任原则,您就可以确定装饰者不是该主题的实现。