组合模式
定义
组合模式(Composite Pattern)将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。组合模式也叫合成模式,有时又叫做部分——整体模式(Part-Whole),主要是用来描述部分与整体的关系。
组合模式跟数据结构中树的结构定义很相似,事实上它就是通过树形结构来组织系统中功能相同但层次分明的子构件的。
组合模式通用类图
Component 抽象构件角色
定义参加组合对象的共有方法和属性。
Leaf 叶子构件
叶子对象,其下不再有其他分支,相当于数据结构中的叶节点。
Composite树枝构件
组合树枝节点和叶子节点形成一个树形结构。
组合模式的优点
l 高层模块调用简单
l 节点自由增加
透明的组合模式
透明模式是把用来组合使用的方法放到抽象类中,使得叶子对象和树枝对象都有相同的结构,这样叶子对象和数值对象对于外界没有区别,但是如果处理不当,在运行期会出现问题。相对来说,上面的组合模式则是安全模式。
举例:
例子来自《大话设计模式》,一般公司里部门之间都有等级结构,而各部门之间又能抽象出相同的功能,所以公司的管理系统可以采用组合模式。
#include <iostream> #include <list> #include <string> using namespace std; class Company{ protected: string m_name; public: Company(string name):m_name(name){} virtual void Add(Company *c)=0; //增加 virtual void Remove(Company *c)=0; //移除 virtual void Display(int depth)=0; //显示 virtual void LineOfDuty()=0; //履行职责 virtual ~Company(){}; }; class ConcreteCompany:public Company{ private: list<Company*> children; public: ConcreteCompany(string name):Company(name){}; void Add(Company *c){children.push_back(c);} void Remove(Company *c){delete c;children.remove(c);} void Display(int depth) { cout<<string(depth,'-')<<m_name<<endl; for(list<Company *>::iterator it=children.begin();it != children.end();it++) { (*it)->Display(depth+2); } } void LineOfDuty() { for(list<Company *>::iterator it=children.begin();it != children.end();it++) (*it)->LineOfDuty(); } ~ConcreteCompany(){ for(list<Company *>::iterator it=children.begin();it != children.end();it++) delete (*it); } }; class HRDepartment:Company{ //人力资源部 public: HRDepartment(string name):Company(name){}; void Add(Company *c){} void Remove(Company *c){} void Display(int depth){cout<<string(depth,'-')+m_name<<endl;} void LineOfDuty(){cout<<m_name<<" 员工招聘培训管理"<<endl;} }; class FinanceDepartment:Company{ //财务部 public: FinanceDepartment(string name):Company(name){} void Add(Company *c){} void Remove(Company *c){} void Display(int depth){cout<<string(depth,'-')+m_name<<endl;} void LineOfDuty(){cout<<m_name<<" 公司财务收支管理"<<endl;} }; int main() { ConcreteCompany *root = new ConcreteCompany("北京总公司"); root->Add((Company *)new HRDepartment("总公司人力资源部")); root->Add((Company *)new FinanceDepartment("总公司财务部")); ConcreteCompany *comp = new ConcreteCompany("上海华东分公司"); comp->Add((Company *)new HRDepartment("华东分公司人力资源部")); comp->Add((Company *)new FinanceDepartment("华东分公司财务部")); root->Add(comp); comp = new ConcreteCompany("南京办事处"); comp->Add((Company *)new HRDepartment("南京办事处人力资源部")); comp->Add((Company *)new FinanceDepartment("南京办事处财务部")); root->Add(comp); comp = new ConcreteCompany("杭州办事处"); comp->Add((Company *)new HRDepartment("杭州办事处人力资源部")); comp->Add((Company *)new FinanceDepartment("杭州办事处财务部")); root->Add(comp); cout<<"结构图:"<<endl; root->Display(1); cout<<"职责:"<<endl; root->LineOfDuty(); delete root; return 0; }
运行结果
昨夜星辰昨夜风,画楼西畔桂堂东。
身无彩凤双飞翼,心有灵犀一点通。
隔座送钩春酒暖,分曹射覆蜡灯红。
嗟余听鼓应官去,走马兰台类转蓬。