介绍
组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。[DP]属于结构型模式之一。
- Component抽象构件角色
定义参加组合对象的共有方法和属性, 可以定义一些默认的行为或属性。 - Leaf叶子构件
叶子对象, 其下再也没有其他的分支, 也就是遍历的最小单位。 - Composite树枝构件
树枝对象, 它的作用是组合树枝节点和叶子节点形成一个树形结构
透明组合模式中,抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法,这样做的好处是确保所有的构件类都有相同的接口。此模式中Component、Leaf、Composite均需要实现所有方法,对于leaf实际上add等方法是无意义的,但对于client来说不需要区分Leaf和Composite。
安全组合模式中,在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。
优点: 高层模块调用简单;节点自由增加
缺点: 树叶和树枝使用实现类,不符合依赖倒置
应用:维护和展示部分–整体关系的场景,如树形菜单、文件和文件夹管理;从一个整体中能够独立出部分模块或功能的场景。
UML图:
#ifndef SIMPLE_COMPOSITE_H
#define SIMPLE_COMPOSITE_H
#include <iostream>
#include <list>
using namespace std;
/**
* @brief The Component class
* Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个
* 接口用于访问和管理Component的子部件。
*/
class Component
{
public:
Component(string name)
{
m_name = name;
}
virtual int add(Component *c) = 0;
virtual int remove(Component *c) = 0;
virtual void display(int depth) = 0;
protected:
string m_name;
};
/**
* @brief The Leaf class
* Leaf在组合中表示叶节点对象,叶节点没有子节点。
*/
class Leaf : public Component
{
public:
Leaf(string name)
:Component(name)
{
}
int add(Component *c) override
{
cout<<" Cannot add to a leaf\n";
return -1;
}
int remove(Component *c) override
{
cout<< " Cannot remove from a leaf\n";
return -1;
}
void display(int depth) override
{
for (int i=0 ;i<depth ;i++) {
cout<<"-";
}
cout<<m_name<<endl;
}
};
/**
* @brief The Composite class
* Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,
* 比如增加Add和删除Remove。
*/
class Composite : public Component
{
public:
Composite(string name)
:Component(name)
{
m_list = new list<Component*>;
m_list->clear();
}
int add(Component *c) override
{
m_list->push_back(c);
return m_list->size();
}
int remove(Component *c) override
{
m_list->remove(c);
return m_list->size();
}
void display(int depth) override
{
for (int i=0 ;i<depth ;i++) {
cout<<"-";
}
cout<<m_name<<endl;
for (list <Component *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
(*it)->display(2+depth);
}
}
private:
list <Component *> *m_list;
};
#endif // SIMPLE_COMPOSITE_H
调用:
//生成树根root,根上长出两叶LeafA和LeafB
Composite *root = new Composite("root");
root->add(new Leaf("Leaf A"));
root->add(new Leaf("Leaf B"));
//根上长出分枝Composite X,分枝上也有两叶LeafXA和LeafXB
Composite *comp = new Composite("Composite X");
comp->add(new Leaf("Leaf XA"));
comp->add(new Leaf("Leaf XB"));
root->add(comp);
//在Composite X.上再长 出分枝CompositeXY,分枝上也有两叶LeafXYA和LeafXYB
Composite *comp2 = new Composite("Composite XY");
comp2->add(new Leaf("Leaf XYA"));
comp2->add(new Leaf("Leaf XYB"));
comp->add(comp2);
//根部又长出两叶LeafC和LeafD
root->add(new Leaf("Leaf C"));
Leaf *le = new Leaf( "Leaf D");
root->add(le);
//可惜LeafD没长牢,被风吹走了
root->remove(le);
root->display(1);
公司管理系统:
UML类图:
代码:
#ifndef COMPANY_MANAGER_H
#define COMPANY_MANAGER_H
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Company
{
public:
Company(string name)
{
m_name = name;
}
virtual int add(Company *) = 0;
virtual int remove(Company *) = 0;
virtual void display(int depth) = 0;
virtual void lineOfDuty() = 0;//旅行职责
protected:
string m_name;
};
/**
* @brief The ConcreteCompany class
* 具体公司类,实现接口,树枝节点
*/
class ConcreteCompany : public Company
{
public:
ConcreteCompany(string name)
:Company(name)
{
m_list = new list <Company *>;
m_list->clear();
}
int add(Company *c) override
{
m_list->push_back(c);
return m_list->size();
}
int remove(Company *c) override
{
m_list->remove(c);
return m_list->size();
}
void display(int depth) override
{
for (int i=0 ;i<depth ;i++) {
cout<<"-";
}
cout<<m_name<<endl;
for (list <Company *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
(*it)->display(2+depth);
}
}
void lineOfDuty() override
{
for (list <Company *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
(*it)->lineOfDuty();
}
}
private:
list <Company *> *m_list;
};
/**
* @brief The HRDepartment class
* 人力资源部门,叶子节点
*/
class HRDepartment : public Company
{
public:
HRDepartment(string name)
:Company(name)
{
}
int add(Company *) override
{
return -1;
}
int remove(Company *) override
{
return -1;
}
void display(int depth) override
{
for (int i=0 ;i<depth ;i++) {
cout<<"-";
}
cout<<m_name<<endl;
}
void lineOfDuty() override
{
cout<<m_name <<" 员工招聘培训管理\n";
}
};
class FinaceDepartment : public Company
{
public:
FinaceDepartment(string name)
:Company(name)
{
}
int add(Company *) override
{
return -1;
}
int remove(Company *) override
{
return -1;
}
void display(int depth) override
{
for (int i=0 ;i<depth ;i++) {
cout<<"-";
}
cout<<m_name<<endl;
}
void lineOfDuty() override
{
cout<<m_name <<" 公司财务收支管理\n";
}
};
#endif // COMPANY_MANAGER_H
调用:
ConcreteCompany *root = new ConcreteCompany("北京分公司");
root->add(new HRDepartment("总公司人力资源部"));
root->add(new FinaceDepartment("总公司财务部"));
ConcreteCompany *comp = new ConcreteCompany("上海华东分公司");
comp->add(new HRDepartment("华东分公司人力资源部"));
comp->add(new FinaceDepartment("华东分公司财务部"));
root->add(comp);
ConcreteCompany *comp1 = new ConcreteCompany("南京华东分公司");
comp1->add(new HRDepartment("南京分公司人力资源部"));
comp1->add(new FinaceDepartment("南京分公司财务部"));
root->add(comp1);
ConcreteCompany *comp2 = new ConcreteCompany("杭州华东分公司");
comp2->add(new HRDepartment("杭州分公司人力资源部"));
comp2->add(new FinaceDepartment("杭州分公司财务部"));
root->add(comp2);
cout<<"\n结构图:\n";
root->display(1);
cout<<"\n职责\n";
root->lineOfDuty();