組合模式(Composite):將對象組合成樹形結構以表示‘部分-整體’的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
何時使用組合模式:
當你發現需求中是體現部分與整體層次的結構時,以及你希望用戶可以忽略組合對象與單個對象的不同,統一地使用組合結構中的所有對象時,就應該考慮使用組合模式。
下面代碼使用組合模式定義了包含人力資源部和財務部這些基本對象和分公司、辦事處等組合對象的類層次結構。基本對象可以被組合成更復雜的組合對象,而這個組合對象又可以被組合,這樣不斷的遞歸下去,客戶端代碼中,任何用到基本對象的地方都可以使用組合對象。簡單的說組合模式可以讓客戶一致地使用組合結構和單個對象。
模式實現:
#ifndef COMPOSITE_H
#define COMPOSITE_H
#include<iostream>
#include<string>
#include<list>
using namespace std;
class Company
{
//friend class ConcreteCompany;
protected:
string name;
public:
Company(){}
Company(string St) :name(St){}
virtual void Add(Company * c){};
virtual void Remove(Company * c){};
virtual void Display(int depth){ cout << name; };
virtual void LineOfDuty(){};
};
class ConcreteCompany :public Company
{
list < Company*> companys;
public:
ConcreteCompany(string st);
void Add(Company * c);
void Remove(Company * c);
void Display(int depth);
void LineOfDuty();
};
ConcreteCompany::ConcreteCompany(string st){ name = st; companys.push_back(new Company(st)); }
void ConcreteCompany::Add(Company * c)
{
companys.push_back(c);
}
void ConcreteCompany::Remove(Company * c)
{
companys.remove(c);
}
void ConcreteCompany::Display(int depth)
{
int n = depth;
while (n)
{
cout << "-"; --n;
}
for each (Company* var in companys)
{
var->Display(depth + 2);
cout << endl;
}
}
void ConcreteCompany::LineOfDuty()
{
for each (Company * var in companys)
{
var->LineOfDuty();
cout << endl;
}
}
class HRDepartment : public Company
{
public:
HRDepartment(string st);
void Add(Company * c);
void Remove(Company * c);
void Display(int depth);
void LineOfDuty();
};
void HRDepartment::Add(Company * c)
{
}
HRDepartment::HRDepartment(string st)
{
name = st;
}
void HRDepartment::Remove(Company * c)
{
}
void HRDepartment::Display(int depth)
{
int n = depth;
while (n)
{
cout << "-"; --n;
}
cout << name;
}
void HRDepartment::LineOfDuty()
{
cout << name << " 員工招聘培訓管理。\n";
}
class FinanceDepartment :public Company
{
public:
FinanceDepartment(string st) { name = st; }
void Add(Company * c){};
void Remove(Company * c){};
void Display(int depth);
void LineOfDuty();
};
void FinanceDepartment::Display(int depth)
{
int n = depth;
while (n)
{
cout << "-"; --n;
}
cout << name;
}
void FinanceDepartment::LineOfDuty()
{
cout << name << " 公司財務收支管理。\n";
}
#endif
客戶端:
#include"Composite.h"
int main()
{
Company* root=new ConcreteCompany ("北京總公司");
root->Add(new HRDepartment("總公司人力資源部"));
root->Add(new FinanceDepartment("總公司財務部"));
ConcreteCompany comp("上海華東分公司");
comp.Add(new HRDepartment("華東分公司人力資源部"));
comp.Add(new FinanceDepartment("華東分公司財務部"));
root->Add(&comp);
ConcreteCompany comp1("南京辦事處");
comp1.Add(new HRDepartment("南京辦事處人力資源部"));
comp1.Add(new FinanceDepartment("南京辦事處財務部"));
comp.Add(&comp1);
ConcreteCompany comp2("杭州辦事處");
comp2.Add(new HRDepartment("杭州辦事處人力資源部"));
comp2.Add(new FinanceDepartment("杭州辦事處財務部"));
comp.Add(&comp2);
root->Display(1);
root->LineOfDuty();
comp.Remove(&comp1);
root->Display(1);
root->LineOfDuty();
return 0;
}