c++设计模式(7)-Composite

一、功能

  表示“部分-整体”关系,并使用户以一致的方式使用单个对象和组合对象。

二、结构图



上图中,也可以做些扩展,根据需要可以将Leaf和Composite做为抽象基类,从中派生出子类来。

三、优缺点

  优点:对于Composite模式,也许人们一开始的注意力会集中在它是如何实现组合对象的。但Composite最重要之处在于用户并不关心是组合对象还是单个对象,用户将以统一的方式进行处理,所以基类应是从单个对象和组合对象中提出的公共接口。
  缺点:Composite最大的问题在于不容易限制组合中的组件。

四、实现

  有时需要限制组合中的组件,即希望一个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 AbstractLeaf1
          {
          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来判断是否允许组合该组件。

五、示例代码

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 ;
          } ;
}


六、实例

  (1)JUnit中就用的是Composite模式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值