一、功能
表示“部分-整体”关系,并使用户以一致的方式使用单个对象和组合对象。
二、结构图
上图中,也可以做些扩展,根据需要可以将Leaf和Composite做为抽象基类,从中派生出子类来。
三、优缺点
优点:对于Composite模式,也许人们一开始的注意力会集中在它是如何实现组合对象的。但Composite最重要之处在于用户并不关心是组合对象还是单个对象,用户将以统一的方式进行处理,所以基类应是从单个对象和组合对象中提出的公共接口。
缺点:Composite最大的问题在于不容易限制组合中的组件。
四、实现
有时需要限制组合中的组件,即希望一个Composite只能有某些特定的Leaf。这个问题我是用多继承和动态类型转换来解决的。假如组合对象Composite1只能包含单个对象ConcreteLeaf1,Composite2可以包含单个对象ConcreteLeaf1和ConcreteLeaf2。如下图所示:
上图中的类层次比较多,使用了AbstractLeaf1和AbstractLeaf2,但没使用AbstractComposite1和AbstractComposite2,这个并不重要,也可以把AbstractLeaf1和AbstractLeaf2去掉,这个并不重要,可以根据具体情况决定要不要。
简单的代码实现如下:
1 class Component 2 { 3 public: 4 virtual void operation() = 0 ; 5 virtual void Add(Component*) {} 6 } ; 7 8 class AbstractComponent1 : virtual public Component {} ; 9 10 class AbstractLeaf1 : virtual public AbstractComponent1 {} ; 11 12 class Composite1 : public AbstractComponent1 13 { 14 public: 15 virtual void operation() { /* do operation */ } 16 virtual void Add(Component*) ; 17 } ; 18 void Composite1::Add(Component *p) 19 { 20 AbstractComponent1 *pc1 = dynamic_cast<ABSTRACTCOMPONENT1*>(p) ; 21 if (pc1 == NULL) return ; 22 // do add operation 23 } 24 25 class AbstractComponent2 : virtual public Component {} ; 26 27 class AbstractLeaf2 : virtual public AbstractComponent2 {} ; 28 29 class Composite2 : public AbstractComponent2 30 { 31 public: 32 virtual void operation() { /* do operation */ } 33 virtual void Add(Component*) ; 34 } ; 35 void Composite2::Add(Component *p) 36 { 37 AbstractComponent2 *pc2 = dynamic_cast<ABSTRACTCOMPONENT2*>(p) ; 38 if (pc2 == NULL) return ; 39 //do add operation 40 } 41 42 class ConcreteLeaf1 : public AbstractLeaf1 43 { 44 public: 45 virtual void operation() { /* do operation */ } 46 } ; 47 48 class ConcreteLeaf2 : public AbstractLeaf1, public AbstractLeaf2 49 { 50 public: 51 virtual void operation() { /* do operation */ } 52 } ; 53 54 客户端代码: 55 Component *pc1 = new ConcreteLeaf1() ; 56 Component *pc2 = new ConcreteLeaf2() ; 57 Component *pc3 = new Composite1() ; 58 Component *pc4 = new Composite2() ; 59 pc3->Add(pc1) ; // ok 60 pc3->Add(pc2) ; // ok 61 pc3->Add(pc3) ; // ok 62 pc3->Add(pc4) ; // fail 63 pc4->Add(pc1) ; // fail 64 pc4->Add(pc2) ; // ok 65 pc4->Add(pc3) ; // fail 66 pc4->Add(pc4) ; // ok
有两点需要注意,一是因为用了多继承,所以需要使用virtual inheritance。二是要用dynamic_cast来判断是否允许组合该组件。
五、示例代码
1 class Component 2 { 3 public: 4 virtual void Operation() = 0 ; 5 virtual void Add(Component*) {} 6 } ; 7 8 class Leaf : public Component 9 { 10 public: 11 virtual void Operation() {} 12 } ; 13 14 class Composite : public Component 15 { 16 public: 17 virtual void Add(Component *p) { _list.push_back(p) ; } 18 virtual void Operation() 19 { 20 vector< Component* >::const_iterator it ; 21 for (it = _list.begin(); it != _list.end(); it++) 22 (*it)->Operation() ; 23 } 24 private: 25 vector< Component* > _list ; 26 } ;
六、实例
(1)JUnit中就用的是Composite模式。