需求分析:很多“部分-整体”的关系,例如:大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包、生活用品中的衣月艮与衣柜以及厨房中的锅碗瓢盆等。
组合模式:一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
优点:
- 使客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
主要角色:
- 抽象构件(Component)角色:为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。
- 树叶构件(Leaf)角色:组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件(Composite)角色:组合中的分支节点对象,它有子节点。实现了抽象构件角色中声明的接口,主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
具体案例:
小码路所在的北京总公司,内部分为人力资源和财务部,在华东开了一家分公司,并分别在杭州和南京有办事处,总公司要求下码路实现全部架构。
第一步:抽象构件角色
代码语言:javascript复制#pragma once
#include <iostream>
using namespace std;
#include <list>
//抽象构件角色
class Company
{
public:
Company(string name)
{
this->name=name;
}
virtual void add(Company *company)=0;
virtual void display(int d)=0;
virtual void duty()=0;
public:
string name;
};
第二步:树叶构件角色
代码语言:javascript复制//具体构件角色
class ConCompany:public Company
{
private:
list<Company*> comList;
public:
ConCompany(string name):Company(name){}
void add(Company *company)override
{
comList.push_back(company);
}
void display(int d)override
{
//输出树型结构
for(int i=0;i<d;i )
{
cout<<"-";
}
cout<<name<<endl;
//向下遍历
for (list<Company*>::iterator it = comList.begin();
it != comList.end(); it)
{
(*it)->display(d 1);
}
}
void duty()override
{
for (list<Company*>::iterator it = comList.begin();
it != comList.end(); it)
{
(*it)->duty();
}
}
};
第三步:树枝构件角色
代码语言:javascript复制//树枝构件角色
//人力资源部
class HRDepartment:public Company
{
public:
HRDepartment(string name):Company(name)
{
}
void add(Company *company)override
{
}
void display(int d)override
{
//输出树形结构的子节点
for(int i=0; i<d; i )
{
cout<<"-";
}
cout<<name<<endl;
}
void duty()override
{
cout<<name << ":员工招聘培训管理"<<endl;
}
};
//财务部
class FinanceDepartment:public Company
{
public:
FinanceDepartment(string name):Company(name)
{
}
void add(Company *company)override
{
}
void display(int d)override
{
//输出树形结构的子节点
for(int i=0; i<d; i )
{
cout<<"-";
}
cout<<name<<endl;
}
void duty()override
{
cout<<name << ":员工招聘培训管理"<<endl;
}
};
第四步:客户端
代码语言:javascript复制#include "c.h"
int main()
{
//总公司
Company *root = new ConCompany("北京总公司");
root->add(new HRDepartment("总公司人力资源部"));
root->add(new FinanceDepartment("总公司财务部"));
//分公司
Company *company = new ConCompany("上海华东分公司");
company->add(new HRDepartment("华东分公司人力资源部"));
company->add(new FinanceDepartment("华东分公司财务部"));
root->add(company);
//办事处
Company *company1 = new ConCompany("南京办事处");
company1->add(new HRDepartment("南京办事处人力资源部"));
company1->add(new FinanceDepartment("南京办事处财务部"));
company->add(company1);
Company *company2 = new ConCompany("杭州办事处");
company2->add(new HRDepartment("杭州办事处人力资源部"));
company2->add(new FinanceDepartment("杭州办事处财务部"));
company->add(company2);
cout<<"结构图:"<<endl;
root->display(1);
cout<<"职责:"<<endl;
root->duty();
}
结果显示: