• 9、组合模式(结构性模式)


            组合模式又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构,以一致的方式处理叶子对象以及组合对象,不以层次高低定义类,都是结点类

           一、传统组合模式

            举例,大学、学院、系,它们之间不是继承关系是组合关系:大学由学院组成,学院由系组成,但是它们都是组织结点,一个大学,n个学院,一个学院m个系,大学、学院是 组合类型的,它们都包含结点成员,系是 叶子类型 的,不包含结点成员

            把大学类、学院类、系类抽象为组织结点类,它们都是组织结点类的子类(其中大学子类、学院子类是组合类型的类,系是叶子类型的类),按照具体依赖抽象原则,以子类共有的属性和行为来定义结点类,代码如下:

    1. //组织结点(基类)Organization
    2. class Organization{ //具体依赖抽象原则
    3. std::string name;//数据成员
    4. public:
    5. Organization( std::string name):name(name) { }//构造函数
    6. virtual ~Organization(){ } //虚析构
    7. //其他成员函数
    8. virtual std::string getName(){ return name; }
    9. virtual void add(Organization* o){ throw "叶子结点没有成员!\n"; }
    10. //virtual void remove( ){ throw "叶子结点没有成员!\n"; }
    11. virtual void print() = 0; //
    12. };

            组合类型的子类University、College,重写基类成员函数,代码几乎一样

    1. //组合类型(子类)University College
    2. //University
    3. class University:public Organization{
    4. std::list ul; //以基类的形式包含其他子类对象
    5. public:
    6. University(std::string name):Organization(name) { }
    7. ~University(){
    8. std:: cout << "~University\n";
    9. for(auto o:ul){ delete o; }
    10. }
    11. //重写
    12. virtual void add(Organization* o){
    13. ul.push_back(o);
    14. }
    15. virtual void print(){
    16. std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分
    17. for( auto o:ul ){
    18. o->print();
    19. }
    20. }
    21. };
    22. //College
    23. class College:public Organization{
    24. std::list cl; //以基类的形式包含其他子类对象
    25. public:
    26. College(std::string name):Organization(name) { }
    27. ~College(){
    28. std:: cout << "~College\n";
    29. for(auto o:cl){ delete o; }
    30. }
    31. //重写
    32. virtual void add(Organization* o){
    33. cl.push_back(o);
    34. }
    35. virtual void print(){
    36. std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分
    37. for( auto o:cl ){
    38. o->print();
    39. }
    40. }
    41. };

            叶子类型的子类(Department)

    1. //叶子类型(子类)Department
    2. class Department:public Organization{
    3. public:
    4. Department(std::string name):Organization(name) { }
    5. ~Department(){
    6. std:: cout << "~Department\n";
    7. }
    8. //重写
    9. virtual void print(){
    10. std::cout << getName() << "\n";
    11. }
    12. };

            头文件及测试代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. int main()
    6. {
    7. University u("清华大学");
    8. Organization* c1 = new College("计算机学院");
    9. Organization* c2 = new College("信息工程学院");
    10. Organization* d = new Department("信息工程");
    11. u.add( c1 );
    12. u.add( c2 );
    13. c2->add( d );
    14. u.print();
    15. //c2->print();
    16. return 0;
    17. }

            二、组合模式的结点设计

            把组合类型的的属性、行为都放到结点,以对象组是否为空来判断是叶子类型的还是组合类型的,这样叶子类型也可以扩展为组合类型,虽然看起来有点混乱,但是确实可行,比如系原来是叶子,现在有了个学生会,添加成员后就可以不是叶子了

    1. #include
    2. #include
    3. #include
    4. #include
    5. //组织结点(基类)Organization
    6. class Organization{ //具体依赖抽象原则
    7. std::string name;//数据成员
    8. std::list ol; //对象组
    9. public:
    10. Organization( std::string name):name(name) { } //构造函数
    11. virtual ~Organization(){ //虚析构
    12. for(auto o:ol){ delete o; }
    13. }
    14. //其他成员函数
    15. virtual void add(Organization* o){ ol.push_back(o); }
    16. virtual void print(){
    17. std::cout << name << "\n";
    18. if( !ol.empty() ) //判断是否是叶子结点
    19. {
    20. for( auto o:ol ){
    21. o->print();
    22. }
    23. }
    24. }
    25. };
    26. //University
    27. class University:public Organization{
    28. public:
    29. University(std::string name):Organization(name) { }
    30. ~University(){ std:: cout << "~University\n"; }
    31. };
    32. //College
    33. class College:public Organization{
    34. std::list cl; //以基类的形式包含其他子类对象
    35. public:
    36. College(std::string name):Organization(name) { }
    37. ~College(){
    38. std:: cout << "~College\n";
    39. }
    40. };
    41. //Department
    42. class Department:public Organization{
    43. public:
    44. Department(std::string name):Organization(name) { }
    45. ~Department(){
    46. std:: cout << "~Department\n";
    47. }
    48. };
    49. //StudentUnion
    50. class StudentUnion:public Organization{
    51. public:
    52. StudentUnion(std::string name):Organization(name) { }
    53. ~StudentUnion(){
    54. std:: cout << "~StudentUnion\n";
    55. }
    56. };
    57. int main()
    58. {
    59. University u("清华大学");
    60. Organization* c1 = new College("计算机学院");
    61. Organization* c2 = new College("信息工程学院");
    62. Organization* d1 = new Department("信息工程");
    63. Organization* d2 = new Department("软件工程");
    64. Organization* s = new StudentUnion("信息工程学生会");
    65. d1->add( s );
    66. c1->add( d2 );
    67. c2->add( d1 );
    68. u.add( c1 );
    69. u.add( c2 );
    70. u.print( );
    71. //c2->print( );
    72. return 0;
    73. }

            三、修改打印函数,打印出树形结构

             1、 修改print

    1. virtual void print( int depth ){
    2. for(int i=0; i< depth; ++i)
    3. std:: cout << "--";
    4. std::cout << name << "\n";
    5. if( !ol.empty() ) //判断是否是叶子结点
    6. {
    7. for( auto o:ol ){
    8. o->print(depth+1);
    9. }
    10. }
    11. }

            2、调用修改为

    1. u.print(0);
    2. //c2->print( 0 );

  • 相关阅读:
    路网编辑器技术预研
    微软:我已把显存优化做到了极致,还有谁?
    麒麟系统开发笔记(六):安装QtCreator开发IDE中的中文输入环境Fcitx输入法
    uniapp的安装与基础
    CF - B. Combinatorics Homework(思维)
    代数与逻辑:作业一 线性模型
    什么是jsp?与servlet区别?request responds cookies session 整理与使用?controller与servlet的区别?
    算法基础学习|排序
    如何保障企业核心应用系统的安全
    mysql5.7数据库安装及性能测试
  • 原文地址:https://blog.csdn.net/tsnotary/article/details/136595750