组合模式又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构,以一致的方式处理叶子对象以及组合对象,不以层次高低定义类,都是结点类
一、传统组合模式
举例,大学、学院、系,它们之间不是继承关系,是组合关系:大学由学院组成,学院由系组成,但是它们都是组织结点,一个大学,n个学院,一个学院m个系,大学、学院是 组合类型的,它们都包含结点成员,系是 叶子类型 的,不包含结点成员
把大学类、学院类、系类抽象为组织结点类,它们都是组织结点类的子类(其中大学子类、学院子类是组合类型的类,系是叶子类型的类),按照具体依赖抽象原则,以子类共有的属性和行为来定义结点类,代码如下:
//组织结点(基类)Organization
class Organization{ //具体依赖抽象原则
std::string name;//数据成员
public:
Organization( std::string name):name(name) { }//构造函数
virtual ~Organization(){ } //虚析构
//其他成员函数
virtual std::string getName(){ return name; }
virtual void add(Organization* o){ throw "叶子结点没有成员!\n"; }
//virtual void remove( ){ throw "叶子结点没有成员!\n"; }
virtual void print() = 0; //
};
组合类型的子类University、College,重写基类成员函数,代码几乎一样
//组合类型(子类)University College
//University
class University:public Organization{
std::list<Organization*> ul; //以基类的形式包含其他子类对象
public:
University(std::string name):Organization(name) { }
~University(){
std:: cout << "~University\n";
for(auto o:ul){ delete o; }
}
//重写
virtual void add(Organization* o){
ul.push_back(o);
}
virtual void print(){
std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分
for( auto o:ul ){
o->print();
}
}
};
//College
class College:public Organization{
std::list<Organization*> cl; //以基类的形式包含其他子类对象
public:
College(std::string name):Organization(name) { }
~College(){
std:: cout << "~College\n";
for(auto o:cl){ delete o; }
}
//重写
virtual void add(Organization* o){
cl.push_back(o);
}
virtual void print(){
std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分
for( auto o:cl ){
o->print();
}
}
};
叶子类型的子类(Department)
//叶子类型(子类)Department
class Department:public Organization{
public:
Department(std::string name):Organization(name) { }
~Department(){
std:: cout << "~Department\n";
}
//重写
virtual void print(){
std::cout << getName() << "\n";
}
};
头文件及测试代码
#include <iostream>
#include <string>
#include <exception>
#include <list>
int main()
{
University u("清华大学");
Organization* c1 = new College("计算机学院");
Organization* c2 = new College("信息工程学院");
Organization* d = new Department("信息工程");
u.add( c1 );
u.add( c2 );
c2->add( d );
u.print();
//c2->print();
return 0;
}
二、组合模式的结点设计
把组合类型的的属性、行为都放到结点,以对象组是否为空来判断是叶子类型的还是组合类型的,这样叶子类型也可以扩展为组合类型,虽然看起来有点混乱,但是确实可行,比如系原来是叶子,现在有了个学生会,添加成员后就可以不是叶子了
#include <iostream>
#include <string>
#include <exception>
#include <list>
//组织结点(基类)Organization
class Organization{ //具体依赖抽象原则
std::string name;//数据成员
std::list<Organization*> ol; //对象组
public:
Organization( std::string name):name(name) { } //构造函数
virtual ~Organization(){ //虚析构
for(auto o:ol){ delete o; }
}
//其他成员函数
virtual void add(Organization* o){ ol.push_back(o); }
virtual void print(){
std::cout << name << "\n";
if( !ol.empty() ) //判断是否是叶子结点
{
for( auto o:ol ){
o->print();
}
}
}
};
//University
class University:public Organization{
public:
University(std::string name):Organization(name) { }
~University(){ std:: cout << "~University\n"; }
};
//College
class College:public Organization{
std::list<Organization*> cl; //以基类的形式包含其他子类对象
public:
College(std::string name):Organization(name) { }
~College(){
std:: cout << "~College\n";
}
};
//Department
class Department:public Organization{
public:
Department(std::string name):Organization(name) { }
~Department(){
std:: cout << "~Department\n";
}
};
//StudentUnion
class StudentUnion:public Organization{
public:
StudentUnion(std::string name):Organization(name) { }
~StudentUnion(){
std:: cout << "~StudentUnion\n";
}
};
int main()
{
University u("清华大学");
Organization* c1 = new College("计算机学院");
Organization* c2 = new College("信息工程学院");
Organization* d1 = new Department("信息工程");
Organization* d2 = new Department("软件工程");
Organization* s = new StudentUnion("信息工程学生会");
d1->add( s );
c1->add( d2 );
c2->add( d1 );
u.add( c1 );
u.add( c2 );
u.print( );
//c2->print( );
return 0;
}
三、修改打印函数,打印出树形结构
1、 修改print
virtual void print( int depth ){
for(int i=0; i< depth; ++i)
std:: cout << "--";
std::cout << name << "\n";
if( !ol.empty() ) //判断是否是叶子结点
{
for( auto o:ol ){
o->print(depth+1);
}
}
}
2、调用修改为
u.print(0);
//c2->print( 0 );