典型的复合模式书籍显示了更精简的例子(显然),其中所有复合项目都有些相关,并且在文件夹和文件示例中经常使用一个常用的方法名称来表示name()
。
我已经在项目中部署了复合模式,它在树状结构中的“整体关系”中很有意义。然而,它们实际上只有两个共同的属性(=方法),每个节点的其余属性或属性虽然相关,但却完全不同。
所以我最终为基础CompositeItem
类中的每个派生类型提供了许多特定函数,我的意思是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
我有这些amy函数的原因之一是因为我需要这些函数来检索每个派生类类型的不同属性或属性。我注意到的一件事是,当你需要检索关于每次的特定信息并在视图中显示它时,很容易将事物整合到复合中,但不是很多 - 这就是我正在做的事情。
我的应用程序已经在树中查看了所有这些内容。我需要在视图的右窗格中显示有关每个节点(=子类)的特定/唯一信息。如果复合材料不合适,是否还有其他适合的模式?
更新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);
现在你可以看到我创建一个物种或组时,我可以直接访问它,我可以设置它的所有属性。
问题是,一旦我将该项添加到Composite容器并唱歌,现在当我稍后需要处理此项时,我必须将其作为CompositeItem *
指针处理。这意味着要么我必须输入强制转换(我认为是坏的),要么使用特定于该项的虚方法来基类来访问它。这是我的问题!虚拟功能太多了!
我想添加以上内容以提供更好的图片并显示我的问题的确切性质,以及是否可以为此方案提供更好的解决方案。谢谢!
答案 0 :(得分:1)
复合模式用于统一处理对象和对象集合,当你想要显示对象的层次结构而不需要处理具体集合(树,列表, graph,...)并且没有处理内容(CompositeItem接口背后的具体类)。
这里似乎你的CompositeItem接口只是许多派生类的基类,这些派生类有一些共同之处并且集合的概念并不存在。从这个意义上讲,复合模式不太适合;但是,此时无法确定您的某个派生类是否为集合。
现在您要问的是,获取几个虚拟方法的接口是否正常,其中一些涉及每个类,而很多只涉及一个派生类?
不,这是代码味道。您应该删除&#34;特定方法&#34;来自您的界面,因为它们没有意义并污染您的界面。
但是你的目的仍然是通过compositeItem接口操作许多这些对象,但是在许多特定方法的帮助下?对吗?
问题在于,您的所有特定内容都无法在新的界面方法下重新组合,并且您不希望依赖dynamic_cast和其他RTTI方法来实现您的目标。
那怎么做?
您有来解耦要应用于的算法的对象层次结构。复合/访客夫妇完全可以达到这个目的。
访问者模式将统一抓取您的TreeView,从一个项目到另一个项目,允许您使用CompositeItem接口方法,或者这些项目上的特定内容。
唯一的缺点是你必须将一些派生类逻辑分发给访问者类