组合模式
定义:
将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
UML图:
在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等,这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备 完全一致的行为 接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的 功能,所以实现它是没有意义的。
1.Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
2.Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
3.Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
使用环境:
在设计中想表示对象的“部分-整体”层次结构;
希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。
安全性与透明性:
组合模式中必须提供对子对象的管理方法,不然无法完成对子对象的添加删除等等操作,也就失去了灵活性和扩展性。但是管理方法是在Component中就声明还是在Composite中声明呢?
一种方式是在Component里面声明所有的用来管理子类对象的方法,以达到Component接口的最大化,这样继承Component的子类都具备了。好处是使客户看来在接口层次上树叶和分支没有区别,它们具备完全一致的行为接口——透明性。但树叶是不存在子类的,因此Component声明的一些方法对于树叶来说是不适用的,实现那些方法是没意义的。这样也就带来了一些安全性问题。
另一种方式就是只在Composite里面声明所有的用来管理子类对象的方法。这样叶子子类就不需要实现那些方法。这样就避免了上一种方式的安全性问题,但是由于叶子和分支有不同的接口,所以又失去了透明性,客户端的调用需要做相应的判断,带来了不便。
#include <list>
#include <string>
#include <iostream>
using namespace std;
class Company//Component
{
public:
Company(char* name):mName(name){}
virtual void attach(Company* cpn){}
virtual void detach(Company* cpn){}
virtual void display(string str){}
virtual void LineOfDuty(string company){}
protected:
char* mName;
list<Company* > mList;
};
class ConcreteCompany:public Company{//Composite
public:
ConcreteCompany(char* name):Company(name){}
virtual void attach(Company* cpn)
{
if(NULL != cpn)
{
mList.push_back(cpn);
}
}
virtual void detach(Company* cpn)
{
if(NULL != cpn)
{
mList.remove(cpn);
}
}
virtual void display(string str)
{
list<Company* >::iterator beg = mList.begin();
cout<<str<<mName<<endl;
str = str + str;
for ( ; beg != mList.end(); beg++)
{
(*beg)->display(str);
}
}
virtual void LineOfDuty(string company)
{
list<Company* >::iterator beg = mList.begin();
string name = mName;
for ( ; beg != mList.end(); beg++)
{
(*beg)->LineOfDuty(name);
}
}
};
class HrDepartment:public Company{//Leaf
public:
HrDepartment(char* name):Company(name){}
virtual void display(string str)
{
cout<<str<<mName<<endl;
}
virtual void LineOfDuty(string company)
{
cout<<company<<"员工招聘培训管理!"<<endl;
}
};
class FinanceDepartment:public Company{//Leaf
public:
FinanceDepartment(char* name):Company(name){}
virtual void display(string str)
{
cout<<str<<mName<<endl;
}
virtual void LineOfDuty(string company)
{
cout<<company<<"公司财务收支管理!"<<endl;
}
};
int main()//客户端
{
ConcreteCompany com1("木鸟飞公司");
FinanceDepartment com2("总公司财务部");
HrDepartment com3("总公司人力部");
com1.attach(&com2);
com1.attach(&com3);
ConcreteCompany com11("木鸟飞东北分公司");
FinanceDepartment com22("东北分公司财务部");
HrDepartment com33("东北分公司人力部");
com11.attach(&com22);
com11.attach(&com33);
com1.attach(&com11);
string str("─");
com1.display(str);
cout<<endl;
com1.LineOfDuty(str);
return 0;
}
上一篇: Laravel 5框架学习之向视图传送数据(进阶篇),laravel框架
下一篇: 暑假图论练习