C++设计模式[七]组合模式



什么是组合模式?

在GOF的《设计模式:可复用面向对象软件的基础》一书中对组合模式是这样说的:将对象组合成树形结构以表示“部分-整体”的层次结构。组合(Composite)模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式(Composite)将小对象组合成树形结构,使用户操作组合对象如同操作一个单个对象。组合模式定义了“部分-整体”的层次结构,基本对象可以被组合成更大的对象,而且这种操作是可重复的,不断重复下去就可以得到一个非常大的组合对象,但这些组合对象与基本对象拥有相同的接口,因而组合是透明的,用法完全一致。

组合模式就是把一些现有的对象或者元素,经过组合后组成新的对象,新的对象提供内部方法,可以让我们很方便的完成这些元素或者内部对象的访问和操作。我们也可以把组合对象理解成一个容器,容器提供各种访问其内部对象或者元素的API,我们只需要使用这些方法就可以操作它了。

UML类图

C++设计模式[七]组合模式_第1张图片

Component:

  1. 为组合中的对象声明接口;
  2. 在适当的情况下,实现所有类共有接口的缺省行为;
  3. 声明一个接口用于访问和管理Component的子组件。

Leaf:

  1. 在组合中表示叶节点对象,叶节点没有子节点;
  2. 在组合中定义叶节点的行为。

Composite:

  1. 定义有子部件的那些部件的行为;
  2. 存储子部件。

Client:

通过Component接口操作组合部件的对象。


#include<iostream>
 #include<string>
 #include<vector>
 using namespace std;

 class Component
 {
 public:
     string m_strName;
     Component(string strName)
     {
         this->m_strName=strName;
     }
     virtual void add(Component *com)=0;
     virtual void dispaly(int nDepth)=0;

 };
 class Leaf:public Component
 {
 public:
     Leaf(string strName):Component(strName){/*this->m_strName=strName;*/}
     virtual void add(Component *com){cout<<"can't add leaf"<<endl;}
     virtual void dispaly(int nDepth)
     {
         string strTemp;
         for(int i=0;i<nDepth;i++)
         {
          strTemp+="-";
         }
         strTemp+=this->m_strName;
         cout<<strTemp<<endl;
     
     }

 };

 class Composite:public Component
 {
 public:
     Composite(string strName):Component(strName){}
     virtual void add(Component *com){m_pCom.push_back(com);}
     virtual void dispaly(int nDepth)
     {
         string strTemp;
         for(int i=0;i<nDepth;i++)
         {
          strTemp+="-";
         }
         strTemp+=this->m_strName;
         cout<<strTemp<<endl;
         vector<Component*>::iterator it=m_pCom.begin();
         while(it!=m_pCom.end())
         {

         (*it)->dispaly(nDepth+2);
          ++it;
         }


     }


 private:
     vector<Component*>m_pCom;
 };


 void main()
 {
     Composite *p=new Composite("总经理");
     Composite *pM=new Composite("技术部门经理");
     p->add(pM);
     pM->add(new Leaf("开发人员A"));
     pM->add(new Leaf("开发人员B"));
     Composite *pS=new Composite("销售部门经理");
     p->add(pS);
     pS->add(new Leaf("销售人员C"));
     pS->add(new Leaf("销售人员D"));
     p->dispaly(1);
     

 };

实现要点

  1. Composite的关键之一在于一个抽象类,它既可以代表Leaf,又可以代表Composite;所以在实际实现时,应该最大化Component接口,Component类应为Leaf和Composite类尽可能多定义一些公共操作。Component类通常为这些操作提供缺省的实现,而Leaf和Composite子类可以对它们进行重定义;
  2. Component是否应该实现一个Component列表,在上面的代码中,我是在Composite中维护的列表,由于在Leaf中,不可能存在子Composite,所以在Composite中维护了一个Component列表,这样就减少了内存的浪费;
  3. 内存的释放;由于存在树形结构,当父节点都被销毁时,所有的子节点也必须被销毁,所以,我是在析构函数中对维护的Component列表进行统一销毁,这样就可以免去客户端频繁销毁子节点的困扰;
  4. 由于在Component接口提供了最大化的接口定义,导致一些操作对于Leaf节点来说并不适用,比如:Leaf节点并不能进行Add和Remove操作,由于Composite模式屏蔽了部分与整体的区别,为了防止客户对Leaf进行非法的Add和Remove操作,所以,在实际开发过程中,进行Add和Remove操作时,需要进行对应的判断,判断当前节点是否为Composite


你可能感兴趣的:(C++设计模式[七]组合模式)