Composite模式
来自KlniuWiki
目录 |
1 问题
在开发中,我们经常可能要递归构建树状的组合结构,Composite模式则提供了很好的解决方案。
2 功能
表示“部分-整体”关系,并使用户以一致的方式使用单个对象和组合对象。
3 结构图
上图中,也可以做些扩展,根据需要可以将Leaf和Composite做为抽象基类,从中派生出子类来。
4 优缺点
优点:对于Composite模式,也许人们一开始的注意力会集中在它是如何实现组合对象的。但Composite最重要之处在于用户并不关心是组合对象还是单个对象,用户将以统一的方式进行处理,所以基类应是从单个对象和组合对象中提出的公共接口。
缺点:Composite最大的问题在于不容易限制组合中的组件。
5 实现
有时需要限制组合中的组件,即希望一个Composite只能有某些特定的Leaf。这个问题我是用多继承和动态类型转换来解决的。假如组合对象 Composite1 只能包含单个对象ConcreteLeaf1,Composite2可以包含单个对象ConcreteLeaf1和 ConcreteLeaf2。如下图所示:

上图中的类层次比较多,使用了AbstractLeaf1和AbstractLeaf2,但没使用AbstractComposite1和 AbstractComposite2,这个并不重要,也可以把AbstractLeaf1和AbstractLeaf2去掉,这个并不重要,可以根据具体情况决定要不要。
简单的代码实现如下:
namespace DesignPattern_Composite { class Component { public: virtual void operation() = 0 ; virtual void Add(Component*) {} } ; class AbstractComponent1 : virtual public Component {} ; class AbstractLeaf1 : virtual public AbstractComponent1 {} ; class Composite1 : public AbstractComponent1 { public: virtual void operation() { /* do operation */ } virtual void Add(Component*) ; } ; void Composite1::Add(Component *p) { AbstractComponent1 *pc1 = dynamic_cast<ABSTRACTCOMPONENT1*>(p) ; if (pc1 == NULL) return ; // do add operation } class AbstractComponent2 : virtual public Component {} ; class AbstractLeaf2 : virtual public AbstractComponent2 {} ; class Composite2 : public AbstractComponent2 { public: virtual void operation() { /* do operation */ } virtual void Add(Component*) ; } ; void Composite2::Add(Component *p) { AbstractComponent2 *pc2 = dynamic_cast<ABSTRACTCOMPONENT2*>(p) ; if (pc2 == NULL) return ; // do add operation } class ConcreteLeaf1 : public AbstractLeaf11 { public: virtual void operation() { /* do operation */ } } ; class ConcreteLeaf2 : public AbstractLeaf1, public AbstractLeaf2 { public: virtual void operation() { /* do operation */ } } ; }
客户端代码:
{ using namespace DesignPattern_Composite ; Component *pc1 = new ConcreteLeaf1() ; Component *pc2 = new ConcreteLeaf2() ; Component *pc3 = new Composite1() ; Component *pc4 = new Composite2() ; pc3->Add(pc1) ; // ok pc3->Add(pc2) ; // ok pc3->Add(pc3) ; // ok pc3->Add(pc4) ; // fail pc4->Add(pc1) ; // fail pc4->Add(pc2) ; // ok pc4->Add(pc3) ; // fail pc4->Add(pc4) ; // ok }
有两点需要注意,一是因为用了多继承,所以需要使用virtual inheritance。二是要用dynamic_cast来判断是否允许组合该组件。
6 示例代码
namespace DesignPattern_Composite { // class Component class Component { public: virtual void Operation() = 0 ; virtual void Add(Component*) {} } ; // class Leaf class Leaf : public Component { public: virtual void Operation() {} } ; // class Composite class Composite : public Component { public: virtual void Add(Component *p) { _list.push_back(p) ; } virtual void Operation() { vector< Component* >::const_iterator it ; for (it = _list.begin(); it != _list.end(); it++) (*it)->Operation() ; } private: vector< Component* > _list ; } ; }
7 实例
Unit中就用的是Composite模式。

8 参见
- c++设计模式(7)-Composite. Henry. 2008-08-29 22:58.
- 设计模式解析之——COMPOSITE模式. K_Eckel. 2005-04-05.