Composite Design 模式可以避免 Collection (List, HashTable) 数据结构吗?

Can the Composite Design pattern avoid a Collection (List, HashTable) data structure?

我想在查看代码时全面理解复合设计模式的所有可能类型。在这段代码中,我有一个复合对象 PeanutButterAndJellySandwich,其中包含 BreadPeanutButterJelly

之所以PeanutButterAndJellySandwhich的字段变量都是food类型是为了计算卡路里

interface Food{
    int calories = 9000;
}


class Bread implements Food{
    private String flour;
    private String salt;

}

class Jelly implements Food{
    private String fruit;
    private String sugar;
}

class PeanutButter implements Food{
    private boolean crunchy;
}

class PeanutButterAndJellySandwich implements Food{
    private Food bread;
    private Food jelly;
    private Food peanutButter;

    public void setBread(Bread bread){this.bread=bread;}
    public void setJelly(Jelly jelly){this.jelly=jelly;}
    public void setPeanutButter(PeanutButter butter){this.peanutButter=butter;}
}

这是遵循复合设计模式还是 PeanutButterAndJellySandwhich 需要类似 foodItems:ArrayList<Food> 的东西。 UML 图看起来非常相似。

我问这个是因为经过大约 5 个小时的搜索后,我没有在任何地方找到明确说明的内容,并且在嵌入式系统之类的应用程序中,我们可能不需要集合数据结构,因为 memory/storage 是有限的。但是,所有在线示例都使用了多种形式的列表。

据我了解,复合模式旨在让您忽略组件(BreadJellyPeanutButterAndJellySandwich 等)及其层次结构之间的差异,使用运行时多态性最有可能。这意味着让 youuniformed 方式(很可能通过循环)处理它们,并让 runtime 休息

因此,由于您的示例只是没有显示此意图并手动处理了那个,我会说这不是复合模式,而是运行时多态性的简单(计划)使用。

但是,您的代码确实抓住了 PeanutButterAndJellySandwichFood 的要点,从而实现了未来的潜在用途(例如 PeanutButterAndJellySandwich 的成分 PeanutButterAndJellySandwich)是复合模式的目标。 (但是你没有在你的代码中表现出这种意图。)


p.s.

  1. 但是设计模式并不是什么神圣的东西。它们旨在作为指南而不是限制。

  2. 我想说这个问题本身没有多大意义,因为设计模式不是为了节省内存,而是为了促进良好的系统设计。所以为了更容易描述和理解,它们以通用的方式描述。

复合模式用于创建树结构。如果你的三明治没有多大意义。您只有一个 Ingredients 的简单层(列表)。除了你想把三明治作为三明治的一部分。对我来说,你的设计刚刚被打破。在适用的地方使用模式。不要应用模式,因为它们存在。

严格来说,复合模式符合 Gamma、Helm 等。 al. 确实讨论了通过界面(在您的情况下是 Food)操纵子项,这往往会引导您实现一个实现,在该实现中,可以将任意数量的子项添加到(或从中删除)任何节点复合树。一个典型的实现可能包括一个抽象的 super-class,它将实现 children-management(添加、删除等),然后具体的 sub-types 将派生出来。像这样的事情:

我在这里做了一些设计选择,但要点是正确的。

但是,更广泛地说,组合 并不需要实施复合模式。没有它,使用组合也很好,事实上 Gamma,Helm 等人也讨论了一个原则。 al. 讨论了支持组合而不是继承,并且与组合模式本身无关。

使用继承作为在程序中重用代码的简便方法很诱人,但这实际上不是继承的意义所在,这就是为什么组合被青睐作为一种防止滥用继承和创建难以管理的代码的方法的原因结果。我担心您使用 Food 接口获取 Calories 成员变量时可能就是这种情况。如果您没有概括您的设计,即您想具体说明 PeanutButterAndJellySandwich 在设计时(在您的代码结构中)包含什么,那么您可能应该做的是声明变量在 PeanutButterAndJellySandwich 中使用它们的具体类型。它们是 Food,这是毫无疑问的,但考虑一下 PeanutButterAndJellySandwich 将如何处理全部声明为 Food 的成员变量?为什么不使用一系列食物?