设计模式之组合模式(composite)

设计模式之组合模式(composite)

概述
组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

生活中的例子
组合模式将对象组合成树形结构以表示"部分-整体"的层次结构。让用户一致地使用单个对象和组合对象。虽然例子抽象一些,但是算术表 达式确实是组合的例子。算术表达式包括操作数、操作符和另一个操作数。操作数可以是数字,也可以是另一个表达式。这样,2+3和(2+3)+(4*6)都 是合法的表达式。(来自http://blog.163.com/renjianqin_1984/blog/static/1328821542010720104922316/)

在上面的图中,Component是组合和个体的基类,单个对象成了Leaf,而组合对象就是Composite,他们同时具有父类的操作。因此在客户看来他们是一致的。这样的话我们可以在Composite下再可以添加Composite对象或者Leaf对象,如此递归成了树形结构。

再来个例子(来自大话设计模式)

设计模式之组合模式(composite)

/*

    有一家公司,总公司在北京,在上海有其在华东地区的分公司,然后在南京和杭州分别有各自的办事处。这里每个地方无论是总部还是分部都会有相同的部门设置,所以可以用Composite模式解决。

/*

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

class Company
{
protected:
    string cname;
public:
    Company(string name):cname(name)
    {
    }
    virtual void Add(Company *c)=0;//增加
    virtual void Remove(Company *c)=0;//删除
    virtual void Display(int depth)=0;//显示
    virtual void LineOfDuty()=0;//职责
};

//具体公司
class ConcreteCompany:public Company
{
private:
    vector<Company*> children;
public:
    ConcreteCompany(string name):Company(name)
    {
    }
    void Add(Company *c)
    {
      children.push_back(c);
    }
    void Remove(Company *c)
    {
      children.erase(&c);
    }
    void Display(int depth)
    {
          string s(depth,'-');
          cout<<s<<cname<<endl;
          vector<Company*>::iterator iter;
          for(iter=children.begin();iter!=children.end();iter++)
            {
               (*iter)->Display(depth+2);
            }
    }
    void LineOfDuty()
    {
        vector<Company*>::iterator iter;
        for(iter=children.begin();iter!=children.end();++iter)
        {
           (*iter)->LineOfDuty();
        }
    }
};

//人事部
class HRDepartment:public Company
{
private:
    vector<Company*> children;
public:
    HRDepartment(string name):Company(name)
    {
    }
    void Add(Company *c)
    {
      children.push_back(c);
    }
    void Remove(Company *c)
    {
      children.erase(&c);
    }
    void Display(int depth)
    {
             string s(depth,'-');
          cout<<s<<cname<<endl;
    }
    void LineOfDuty()
    {
       cout<<cname<<"\t员工招聘培训管理"<<endl;
    }
};

//财务部
class FinanceDepartment:public Company
{
private:
    vector<Company*> children;
public:
    FinanceDepartment(string name):Company(name)
    {
    }
    void Add(Company *c)
    {
      children.push_back(c);
    }
    void Remove(Company *c)
    {
      children.erase(&c);
    }
    void Display(int depth)
    {
             string s(depth,'-');
          cout<<s<<cname<<endl;
    }
    void LineOfDuty()
    {
        cout<<cname<<"\t公司财务收支管理"<<endl;
    }
};

int main()
{
   ConcreteCompany *c=new ConcreteCompany("北京总公司");
   c->Add(new HRDepartment("总公司人力资源部"));
   c->Add(new FinanceDepartment("总公司财务管理部"));
   
   ConcreteCompany *c1=new ConcreteCompany("上海华东分公司");
   c1->Add(new HRDepartment("华东分公司人力资源部"));
   c1->Add(new FinanceDepartment("华东分公司财务部"));
   c->Add(c1);

   ConcreteCompany *c2=new ConcreteCompany("南京办事处");
   c1->Add(c2);
   c2->Add(new HRDepartment("南京办事处人力资源部"));
   c2->Add(new FinanceDepartment("南京办事处财务部"));


   ConcreteCompany *c3=new ConcreteCompany("杭州办事处");
   c1->Add(c3);
   c3->Add(new HRDepartment("杭州办事处人力资源部"));
   c3->Add(new FinanceDepartment("杭州办事处财务部"));
   

   cout<<"结构图:"<<endl;
   c->Display(1);
   cout<<endl;
   cout<<"职责:"<<endl;
   c->LineOfDuty();

   return 0;

}


运行结果:

设计模式之组合模式(composite)

这就是一个树形结构,子节点都可以跟父节点一样拥有相同的职能,但是他们所处的层次却是清晰地分开了,这就是Composite模式的好处。


注:组合模式一种继承关系,派生类中含有包含基类指针的容器。

组合模式和其他相关模式

1)装饰模式(Decorator模式)经常与Composite模式一起使用。当装饰和组合一起使用时,它们

通常有一个公共的父类。因此装饰必须支持具有 Add、Remove和GetChild 操作的Component接口。

2)Flyweight模式让你共享组件,但不再能引用他们的父部件。

3)(迭代器模式)Itertor可用来遍历Composite。

4)(观察者模式)Visitor将本来应该分布在Composite和L e a f类中的操作和行为局部化。


;