3

我在 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());        
    }
}

有人可以指出/解释上述代码如何遵循组合吗?

4

1 回答 1

1

之间的相似性aggregationcomposition使它们经常被用作同义词。IMO,如果您没有理由做出区分,那么不值得花时间争论它实际上是什么。如果您确实有原因,您可能已经知道它属于哪个原因。

它们在概念上足够接近,以至于它们就是您对待它们的方式。如果您将关系作为一个单元使用,那么它是一个composition. 如果您彼此独立地与它们交互,那么它是一个aggregation.

主要细节在于它为什么重要。我能想到的区分两者的主要需要是垃圾收集。容器的aggregation属性在其容器上下文之外可能仍然有意义。容器的一个composition属性应该随容器一起销毁。

当我们观察到与定义相反的对象存在的价值时,我相信它可以表达为两者兼而有之。在某些情况下,您可能希望只销毁容器并保留内容物 ( aggregation)。然而,没有它的委托,它是没有意义的。这在某种程度上定义了inverse composition. 您永远不会想要摧毁孩子并保留装饰者。

虽然Science实际上是一个具体Girl的,但实现Science.getDescription会覆盖基本实现以将请求委托给具体Girl。这个实现细节使女孩在没有使用有效实现Science初始​​化的情况下变得毫无意义。Girl

如果存在本身是没有意义的,那么它通常aggregation不是 a 而是可能是 a composition

顺便说一句,装饰器通过实现接口而不是继承基类来更清楚地表达。遵循单一职责原则,您可以确定装饰器不是主题的实现。

于 2017-06-09T21:41:19.667 回答