• 设计模式之十:Composite(转)


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

      二、结构图

      上图中,也可以做些扩展,根据需要可以将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
    View Code

    有两点需要注意,一是因为用了多继承,所以需要使用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 } ;      
    View Code

    六、实例

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

  • 相关阅读:
    scrapy框架(一)
    selenium爬取京东商品信息
    自动化测试工具selenium的使用
    xpath选择器的使用
    爬取网页数据实例
    爬虫实操
    爬虫之`beautifulsoup4`模块
    DNS学习笔记
    MongoDB集群部署
    MongoDB单机部署
  • 原文地址:https://www.cnblogs.com/wangzhijun/p/3470439.html
Copyright © 2020-2023  润新知