C++设计模式11-组合模式----靠着大树好乘凉

               

定义

(GoF《设计模式》):将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组成

① Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。

② Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。

③ Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

适用性

以下情况下适用Composite模式:

1.你想表示对象的部分-整体层次结构

2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

例子

我们每天在公司上班,我们的公司其实就是一个树型结构的,最上边是总公司,总公司下面还有很多子公司而每个子公司有很很多部门。这样整个大公司就是一颗大树,每个子公司同时也是一颗小叔

首先是公司的抽象接口

// 公司抽象类 class Company{public :    Company(std::string name)    :m_name(name)    {    }    virtual ~Company( )    {    }    virtual void Add(Company *pCompany)        // 增加子公司    {    }    virtual void Show(int depth) = 0;               // 显示部门protected :    std::string m_name;                         // 显示公司名字};


其次是公司的实现

// 公司类 class ConcreteCompany : public Company{public :    ConcreteCompany(std::string name)    :Company(name)    {    }    virtual ~ConcreteCompany( ){ };         // 虚析构函数    void Add(Company *company)     // 添加子公司 {  this->m_companyList.push_back(company);        // 将子公司或者部门加入到公司的列表中 }    void Show(int depth)               // 显示公司部门 {  for(int pos = 0; pos < depth; pos++)  {   std::cout <<"-";  }  std::cout <<this->m_name <<std::endl;  for(std::list<Company *>::iterator it = this->m_companyList.begin( );   it != this->m_companyList.end( );   ++it)  {            (*it)->Show(depth + 2);  } }protected :    std::list<Company *> m_companyList;          // 下属公司列表};


接着是财务部门的实现

// 财务部门 class FinaceDepartment : public Company{public :    FinaceDepartment(std::string name)    :Company(name)    {    }    virtual ~FinaceDepartment( )    {    } void Show(int depth)               // 显示公司部门 {  for(int pos = 0; pos < depth; pos++)  {   std::cout <<"-";  }  std::cout <<this->m_name <<std::endl; }};


然后是人力资源部门

// 人力部门 class HRDepartment : public Company{public :    HRDepartment(std::string name)    :Company(name)    {    }    virtual ~HRDepartment( ){ };         // 虚析构函数 void Show(int depth)               // 显示公司部门 {  for(int pos = 0; pos < depth; pos++)  {   std::cout <<"-";  }  std::cout <<this->m_name <<std::endl; }};


最后是客户端代码

int main(){    // 总公司    Company *root = new ConcreteCompany("总公司");    Company *rootHR = new HRDepartment("人力资源部");    Company *rootFI = new FinaceDepartment("财务部");    root->Add(rootHR);    root->Add(rootFI);    // 分公司A    Company *left = new ConcreteCompany("分公司A");    Company *leftHR = new HRDepartment("分公司A人力资源部");    Company *leftFI = new FinaceDepartment("分公司A财务部");    left->Add(leftHR);    left->Add(leftFI);    root->Add(left);    // 分公司B    Company *right = new ConcreteCompany("分公司B");    Company *righHR = new HRDepartment("分公司B人力资源部");    Company *righFI = new FinaceDepartment("分公司B财务部");    right->Add(righHR);    right->Add(righFI);    root->Add(right);    root->Show(0);    return 0;}


总结

组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。

如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。本章使用了一个文件系统的例子来举例说明了组合模式的用途。在这个例子中,文件和目录都执行相同的接口,这是组合模式的关键。通过执行相同的接口,你就可以用相同的方式对待文件和目录,从而实现将文件或者目录储存为目录的子级元素。

           

猜你喜欢

转载自blog.csdn.net/qq_44925149/article/details/89810669