如果复合模式中的每个复合项目都有许多自己独特的属性,可以吗?

Is it okay if each composite item in composite pattern has lots of unique properties of its own?

典型的复合模式书籍显示了更精简的示例(显然),其中所有复合项目都有些相关,并且经常使用一种通用方法名称进行说明,例如文件夹和文件示例中的 name()

我已经在项目中部署了复合模式,它在 'whole-part relationship' 中在树状结构中很有意义。然而,它们实际上只有两个共同的属性(=方法),它们的其余属性或每个节点的属性虽然相关但完全不同。

所以我最终为基础 CompositeItem class 中的每个派生类型提供了很多特定函数,我的意思是我用以下示例说明的 10 到 15 种方法.

class CompositeItem
    {
        CompositeItem();

        // common methods, applies to all derived classes
        virtual void hello();
        virtual void foo();

        // these apply only to derived1 class
        virtual void method1();
        virtual void method2();
        virtual void method3();
        virtual void method4();
        virtual void method5();
        virtual void method6();
        virtual void method7();
        virtual void method8();
        virtual void method9();
        virtual void method10();

        // these applies to only derived2 class
        virtual void method11();
        virtual void method12();
        virtual void method13();
        virtual void method14();
        virtual void method15();
        virtual void method17();
        virtual void method17();
        virtual void method18();
        virtual void method19();
        virtual void method20();

        // these applies to only derived3 class
        virtual void method21();
        virtual void method22();
        virtual void method23();
        virtual void method24();
        virtual void method25();
        virtual void method26();
        virtual void method27();
        virtual void method28();
        virtual void method29();
        virtual void method30(;)

        // these applies to only derived4 class
        virtual void method31();
        virtual void method32();
        virtual void method33();
        virtual void method34();
        virtual void method35();
        virtual void method36();
        virtual void method37()
        virtual void method38();
        virtual void method39();
        virtual void method40();
    }

因为我还没有真正看到复合材料在这个规模上的运作,所以我正在寻找验证,这听起来正常还是有任何危险信号?

我知道我没有包括关于项目的太具体的信息,但考虑到所有项目仅共享 2 种方法,但每个项目都有 10 到 15 种不同的方法,只有该派生项目独有,这听起来不错并且总体上符合模式?

更新 1

我拥有这些 so amy 函数的原因之一是因为我需要这些函数来检索每个派生的 class 类型的不同属性或特性。我注意到的一件事是,将事物填充到复合材料中很容易,但当您需要每次检索特定信息并将其显示在视图中时,就不是那么容易了——这就是我正在做的。

我的应用程序在树中留下了所有这些东西的视图。我确实需要在视图的右窗格中显示有关每个节点 (=subclass) 的 specific/unique 信息。如果 composite 不合适,还有其​​他合适的模式吗?

更新 2

我可以通过以下方式总结我对合成的困境(注意代码写得飞快,请原谅错别字):

class CompositeItem 
{ 
    virtual void add(CompositeItem *item);
};

class Species : public CompositeItem 
{
    QList< CompositeItem *> species;
}

class Mammals: public CompositeItem 
{
    QList<CompositeItem *> mammals;
    // assume I have 10 methods here for various attributes about mammals

}

class Tiger: public CompositeItem
{
    // assume I have 10 methods to various specific attributes about tigers

}

CompositeItem * species = new Species;

CompositeItem * mammals = new Mammals( lives_on_land, has_4_legs, etc);

CompositeItem * tiger = new Tiger(eats_meat, hunts_alone, etc);

mammals->add(tiger);
species.add(mammals);

现在你可以看到当我创建一个物种或组时,我可以直接访问它并且我可以设置它的所有属性。

问题是,一旦我将该项目添加到复合容器并关闭,现在当我稍后需要处理该项目时,我必须将其作为 CompositeItem * 指针处理。这意味着我要么必须键入 cast(我认为不好),要么使用特定于该项目的虚拟方法来访问它 class 。这是我的问题!虚函数太多了!

我想添加以上内容以提供更好的图片并显示我的问题的确切性质,以及是否可以针对这种情况提供更好的解决方案。谢谢!

复合模式是为了统一处理对象和对象集合,当你想显示对象的层次结构而不关心具体的集合时,正是这种情况(树、列表、图形、...)并且不考虑内容(CompositeItem 界面后面的具体 classes)。

在这里,您的 CompositeItem 接口似乎只是许多派生的 class 的基础 class,它们有一些共同点,集合的概念并不真正存在。从这个意义上说,复合模式不太适合;但是,在这一点上不可能说你派生的 class 是否是一个集合。

现在你问的是获取多个虚方法的接口是否正常,其中一些涉及每个classes,很多只涉及一个派生class ?

不,这是一种代码味道。您应该从您的界面中删除 "specific methods",因为它们没有意义并且会污染您的界面。

但是您的目的仍然是通过 compositeItem 接口操作其中的许多对象,但要借助许多特定方法?对吗?

问题是您的所有特定内容无法在新的接口方法下重新组合,您不想依赖 dynamic_cast 和其他 RTTI 方法来实现您的目标。

那么怎么做呢?

您必须解耦要应用的算法的对象层次结构。 Composite/Visitor夫妻俩完全符合这个目的。

访问者模式将统一抓取您的 TreeView,从一个项目到另一个项目,允许您使用 CompositeItem 接口方法,或者这些项目的特定内容。

唯一的缺点是您必须将一些派生的 class 逻辑分发给访问者 class(es)

编辑: https://sourcemaking.com/design_patterns/visitor