组合模式又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构,以一致的方式处理叶子对象以及组合对象,不以层次高低定义类,都是结点类
举例,大学、学院、系,它们之间不是继承关系,是组合关系:大学由学院组成,学院由系组成,但是它们都是组织结点,一个大学,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
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
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
- #include
- #include
- #include
-
- 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
- #include
- #include
- #include
-
- //组织结点(基类)Organization
- class Organization{ //具体依赖抽象原则
- std::string name;//数据成员
- std::list
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
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 );