找回密码
 立即注册
首页 业界区 业界 【组合设计模式详解】C/Java/JS/Go/Python/TS不同语言实 ...

【组合设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

訾懵 2025-6-6 09:40:45
简介

组合模式(Composite Pattern),又叫部分整体模式,是一种结构型设计模式。用于把一组类似的对象当作一个单一的对象来看。组合模式依据树形结构来组合对象,用不同组件来构建某个部分或整体对象。
如果你需要实现树状对象结构,可以使用组合模式。如果你希望客户端代码以相同方式处理简单和复杂元素,可以使用该模式。
作用


  • 符合开闭原则。无需更改现有代码,就可以在应用中添加新元素,使之成为对象树的一部分。
  • 模糊了简单元素和复杂元素的概念,程序可以像处理简单元素一样来处理复杂元素,从而使得程序与复杂元素的内部结构解耦。
实现步骤


  • 创建抽象构件(Component)接口,用于声明树叶构件和树枝构件的默认行为。
  • 创建树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
  • 定义树叶构件(Leaf)角色:是组合中的叶子节点对象,它没有子节点,用于继承或实现抽象构件。
UML

1.png


 
Java语言代码

基础部件接口
  1. // OrganizationComponent.java 定义部件接口或抽象类,分支和叶子节点遵循该类约定
  2. public interface OrganizationComponent {
  3.    public void add(OrganizationComponent component);
  4.    public void remove(OrganizationComponent component);
  5.    public OrganizationComponent getChild(int index);
  6.    public void operation();
  7.    public String getName();
  8. }
复制代码
 
具体部件实现
  1. // CompanyComposite.java 实现部件的树枝构件1
  2. public class CompanyComposite implements OrganizationComponent {
  3.    private String name;
  4.    private List<OrganizationComponent> children = new ArrayList<OrganizationComponent>();
  5.    public CompanyComposite(String name) {
  6.       this.name = name;
  7.    }
  8.    public void add(OrganizationComponent component) {
  9.       children.add(component);
  10.    }
  11.    public void remove(OrganizationComponent component) {
  12.       children.remove(component);
  13.    }
  14.    public OrganizationComponent getChild(int index) {
  15.       return children.get(index);
  16.    }
  17.    public void operation() {
  18.       System.out.println(this.getClass().getName() + " CompanyComposite::operation() " + this.name);
  19.       for (Object component : children) {
  20.          ((OrganizationComponent) component).operation();
  21.       }
  22.    }
  23.    public String getName() {
  24.       return name;
  25.    }
  26. }<br>
  27. // DepartmentComposite.java  实现部件的树枝构件2
  28. public class DepartmentComposite implements OrganizationComponent {
  29.    private String name;
  30.    private List<OrganizationComponent> children = new ArrayList<OrganizationComponent>();
  31.    public DepartmentComposite(String name) {
  32.       this.name = name;
  33.    }
  34.    public void add(OrganizationComponent component) {
  35.       children.add(component);
  36.    }
  37.    public void remove(OrganizationComponent component) {
  38.       children.remove(component);
  39.    }
  40.    public OrganizationComponent getChild(int index) {
  41.       return children.get(index);
  42.    }
  43.    public void operation() {
  44.       System.out.println(this.getClass().getName() + " DepartmentComposite::operation() " + this.name);
  45.       for (Object component : children) {
  46.          ((OrganizationComponent) component).operation();
  47.       }
  48.    }
  49.    public String getName() {
  50.       return name;
  51.    }
  52. }<br>
  53. // EmployeeLeaf.java 实现部件的叶子节点,叶子节点不能再含有子节点
  54. public class EmployeeLeaf implements OrganizationComponent {
  55.    private String name;
  56.    public EmployeeLeaf(String name) {
  57.       this.name = name;
  58.    }
  59.    // 叶子节点不能再增加内容
  60.    public void add(OrganizationComponent component) {
  61.       System.out.println("Leaf can't add.");
  62.    }
  63.    // 叶子节点没有移除内容
  64.    public void remove(OrganizationComponent component) {
  65.       System.out.println("Leaf can't remove.");
  66.    }
  67.    // 叶子节点无获取子节点
  68.    public OrganizationComponent getChild(int index) {
  69.       System.out.println("Leaf can't getChild.");
  70.       return null;
  71.    }
  72.    public void operation() {
  73.       System.out.println(this.getClass().getName() + " EmployeeLeaf::operation() " + this.name);
  74.    }
  75.    public String getName() {
  76.       return name;
  77.    }
  78. }
复制代码
 
测试调用
  1.     /**
  2.      * 组合模式依据树形结构来组合对象,用不同组件来构建整体对象。
  3.      * 不同组件之间有相同的接口约束,有不同的具体实现。
  4.      * 先定义顶级节点,然后陆续加入枝叶节点和叶子节点,这样不断添加,将零散的个体组成一个整体。
  5.      */
  6.     // 通过组合模型组合了一个部件,分支和节点可以随意增删
  7.     OrganizationComponent com = new CompanyComposite("西天旅游有限公司");
  8.     OrganizationComponent com1 = new DepartmentComposite("总裁办");
  9.     OrganizationComponent com2 = new DepartmentComposite("行动队");
  10.     OrganizationComponent com3 = new DepartmentComposite("后勤组");
  11.     OrganizationComponent leaf1 = new EmployeeLeaf("唐三藏");
  12.     OrganizationComponent leaf2 = new EmployeeLeaf("孙悟空");
  13.     OrganizationComponent leaf3 = new EmployeeLeaf("猪悟能");
  14.     OrganizationComponent leaf4 = new EmployeeLeaf("沙悟净");
  15.     com.add(com1);
  16.     com.add(com2);
  17.     com.add(com3);
  18.     // leaf1属于com1
  19.     com1.add(leaf1);
  20.     // leaf2, leaf3属于com2
  21.     com2.add(leaf2);
  22.     com2.add(leaf3);
  23.     // 添加再删除
  24.     DepartmentComposite dept1 = new DepartmentComposite("小分队");
  25.     com2.add(dept1);
  26.     EmployeeLeaf tmp1 = new EmployeeLeaf("临时工");
  27.     dept1.add(tmp1);
  28.     dept1.remove(tmp1);
  29.     // leaf4属于com3
  30.     com3.add(leaf4);
  31.     // 执行全部节点动作
  32.     com.operation();
  33.     // 获取某个节点
  34.     OrganizationComponent employee = (EmployeeLeaf) com.getChild(1).getChild(0);
  35.     System.out.println(employee.getName());
复制代码
 
C语言代码
  1. func.h 自定义头文件
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. // 定义部件接口或抽象类,分支和叶子节点遵循该类约定
  7. typedef struct OrganizationComponent
  8. {
  9.     char name[200];
  10.     void (*add)(struct OrganizationComponent *, struct OrganizationComponent *);
  11.     void (*remove)(struct OrganizationComponent *, struct OrganizationComponent *);
  12.     struct OrganizationComponent *(*get_child)(struct OrganizationComponent *, int);
  13.     void (*operation)(struct OrganizationComponent *);
  14.     int children_size;
  15.     struct OrganizationComponent **children;
  16.     // 如果是柔型数组,则自动扩展数组长度,但可能导致出现乱码现象,故采取固定长度数组
  17.     // struct OrganizationComponent *children[];
  18. } OrganizationComponent;
  19. void add_component(OrganizationComponent *, OrganizationComponent *);
  20. void remove_component(OrganizationComponent *, OrganizationComponent *);
  21. OrganizationComponent *get_child_component(OrganizationComponent *, int);
  22. void print_children(OrganizationComponent *children[], int children_size);
  23. // 实现部件的树枝构件1
  24. typedef struct CompanyComposite
  25. {
  26.     char name[200];
  27.     void (*add)(struct OrganizationComponent *, struct OrganizationComponent *);
  28.     void (*remove)(struct OrganizationComponent *, struct OrganizationComponent *);
  29.     struct OrganizationComponent *(*get_child)(struct OrganizationComponent *, int);
  30.     void (*operation)(struct CompanyComposite *);
  31.     int children_size;
  32.     struct OrganizationComponent **children;
  33. } CompanyComposite;
  34. CompanyComposite *company_composite_constructor(char *name);
  35. // 实现部件的树枝构件2
  36. typedef struct DepartmentComposite
  37. {
  38.     char name[200];
  39.     void (*add)(struct OrganizationComponent *, struct OrganizationComponent *);
  40.     void (*remove)(struct OrganizationComponent *, struct OrganizationComponent *);
  41.     struct OrganizationComponent *(*get_child)(struct OrganizationComponent *, int);
  42.     void (*operation)(struct DepartmentComposite *);
  43.     int children_size;
  44.     struct OrganizationComponent **children;
  45. } DepartmentComposite;
  46. DepartmentComposite *department_composite_constructor(char *name);
  47. // 实现部件的叶子节点,叶子节点不能再含有子节点
  48. typedef struct EmployeeLeaf
  49. {
  50.     char name[200];
  51.     void (*add)(struct OrganizationComponent *, struct OrganizationComponent *);
  52.     void (*remove)(struct OrganizationComponent *, struct OrganizationComponent *);
  53.     struct OrganizationComponent *(*get_child)(struct OrganizationComponent *, int);
  54.     void (*operation)(struct EmployeeLeaf *);
  55.     int children_size;
  56.     struct OrganizationComponent **children;
  57. } EmployeeLeaf;
  58. EmployeeLeaf *employee_leaf_constructor(char *name);
复制代码
 
基础部件接口
  1. // organization_component.c 定义部件接口或抽象类,分支和叶子节点遵循该类约定
  2. #include "func.h"
  3. // 定义部件接口或抽象类,分支和叶子节点遵循该类约定
  4. // C语言没有接口和抽象类,用struct替代,同时把公共函数声明在这里
  5. // 添加一个组件到子节点中
  6. void add_component(OrganizationComponent *parent, OrganizationComponent *component)
  7. {
  8.   // 先将原数组保留下来
  9.   OrganizationComponent **old_children = parent->children;
  10.   parent->children_size += 1;
  11.   // 新申请空间给子节点数组
  12.   parent->children = (OrganizationComponent **)calloc(parent->children_size, sizeof(OrganizationComponent *));
  13.   for (int i = 0; i < parent->children_size - 1; i++)
  14.   {
  15.     parent->children[i] = old_children[i];
  16.   }
  17.   // 将组件追加到子节点数组中
  18.   parent->children[parent->children_size - 1] = component;
  19.   free(old_children);
  20. }
  21. // 移除第一个匹配的子节点
  22. void remove_component(OrganizationComponent *parent, OrganizationComponent *component)
  23. {
  24.   int size = parent->children_size;
  25.   // 初始化组件id大于数组长度
  26.   int com_idx = size;
  27.   for (int i = 0; i < size; i++)
  28.   {
  29.     // 找到第一个匹配的组件下标
  30.     if (parent->children[i] == component)
  31.     {
  32.       com_idx = i;
  33.     }
  34.     // 自匹配项开始,后项逐个往前移动1位
  35.     if (i >= com_idx)
  36.     {
  37.       parent->children[i] = parent->children[i + 1];
  38.       // 最后一项置空且总长度减少1位
  39.       if (i == size - 1)
  40.       {
  41.         parent->children[i] = NULL;
  42.         parent->children_size -= 1;
  43.       }
  44.     }
  45.   }
  46. }
  47. // 打印全部子节点
  48. void print_children(OrganizationComponent *children[], int children_size)
  49. {
  50.   for (int i = 0; i < children_size; i++)
  51.   {
  52.     printf("\r\n    children[%d]=%s", i, children[i]->name);
  53.   }
  54. }
  55. // 根据下标获取子节点
  56. OrganizationComponent *get_child_component(OrganizationComponent *component, int index)
  57. {
  58.   return component->children[index];
  59. }
复制代码
 
具体部件实现
  1. // company_composite.c 实现部件的树枝构件1
  2. #include "func.h"
  3. // 实现部件的树枝构件1
  4. void company_composite_operation(CompanyComposite *component)
  5. {
  6.   printf("\r\n CompanyComposite::operation() [name=%s]", component->name);
  7.   print_children(component->children, component->children_size);
  8.   for (int i = 0; i < component->children_size; i++)
  9.   {
  10.     if (component->children[i] != NULL)
  11.     {
  12.       component->children[i]->operation(component->children[i]);
  13.     }
  14.   }
  15. }
  16. // 创建CompanyComposite对象
  17. CompanyComposite *company_composite_constructor(char *name)
  18. {
  19.   OrganizationComponent *component = (OrganizationComponent *)malloc(sizeof(OrganizationComponent));
  20.   strncpy(component->name, name, 200);
  21.   component->add = &add_component;
  22.   component->remove = &remove_component;
  23.   component->children_size = 0;
  24.   component->get_child = &get_child_component;
  25.   // 转为CompanyComposite
  26.   CompanyComposite *company_composite = (CompanyComposite *)component;
  27.   company_composite->operation = &company_composite_operation;
  28.   return company_composite;
  29. }<br><br>
  30. // department_composite.c  实现部件的树枝构件2
  31. #include "func.h"
  32. // 实现部件的树枝构件2
  33. void department_composite_operation(DepartmentComposite *component)
  34. {
  35.   printf("\r\n DepartmentComposite::operation() [name=%s]", component->name);
  36.   print_children(component->children, component->children_size);
  37.   for (int i = 0; i < component->children_size; i++)
  38.   {
  39.     if (component->children[i] != NULL)
  40.     {
  41.       component->children[i]->operation(component->children[i]);
  42.     }
  43.   }
  44. }
  45. // 创建DepartmentComposite对象
  46. DepartmentComposite *department_composite_constructor(char *name)
  47. {
  48.   OrganizationComponent *component = (OrganizationComponent *)malloc(sizeof(OrganizationComponent));
  49.   strncpy(component->name, name, 200);
  50.   component->add = &add_component;
  51.   component->remove = &remove_component;
  52.   component->children_size = 0;
  53.   component->get_child = &get_child_component;
  54.   // 转为DepartmentComposite
  55.   DepartmentComposite *department_composite = (DepartmentComposite *)component;
  56.   department_composite->operation = &department_composite_operation;
  57.   return department_composite;
  58. }<br><br>
  59. // employee_leaf.c 实现部件的叶子节点,叶子节点不能再含有子节点
  60. #include "func.h"
  61. // 实现部件的叶子节点,叶子节点不能再含有子节点
  62. // 叶子节点不能再增加内容
  63. void add_leaf_component(OrganizationComponent *parent, OrganizationComponent *component)
  64. {
  65.   printf("\r\n Leaf can't add.");
  66. }
  67. // 叶子节点没有移除内容
  68. void remove_leaf_component(OrganizationComponent *parent, OrganizationComponent *component)
  69. {
  70.   printf("\r\n Leaf can't remove.");
  71. }
  72. // 叶子节点不能获取子节点
  73. OrganizationComponent *get_leaf_child_component(OrganizationComponent *component, int index)
  74. {
  75.   printf("\r\n Leaf can't get_child.");
  76.   return NULL;
  77. }
  78. // 子节点的操作函数
  79. void employee_leaf_operation(EmployeeLeaf *component)
  80. {
  81.   printf("\r\n EmployeeLeaf::operation() [name=%s]", component->name);
  82. }
  83. // 创建EmployeeLeaf对象
  84. EmployeeLeaf *employee_leaf_constructor(char *name)
  85. {
  86.   OrganizationComponent *component = (OrganizationComponent *)malloc(sizeof(OrganizationComponent));
  87.   strncpy(component->name, name, 200);
  88.   component->children_size = 0;
  89.   component->add = &add_leaf_component;
  90.   component->remove = &remove_leaf_component;
  91.   component->get_child = &get_leaf_child_component;
  92.   // 转为EmployeeLeaf
  93.   EmployeeLeaf *employee_leaf = (EmployeeLeaf *)component;
  94.   employee_leaf->operation = &employee_leaf_operation;
  95.   return employee_leaf;
  96. }
复制代码
 
测试调用
  1.    /**
  2.     * 组合模式依据树形结构来组合对象,用不同组件来构建整体对象。
  3.     * 不同组件之间有相同的接口约束,有不同的具体实现。
  4.     * 先定义顶级节点,然后陆续加入枝叶节点和叶子节点,这样不断添加,将零散的个体组成一个整体。ss
  5.     */
  6.    // 通过组合模型组合了一个部件,分支和节点可以随意增删
  7.    OrganizationComponent *com = (OrganizationComponent *)company_composite_constructor("西天旅游有限公司");
  8.    OrganizationComponent *com1 = (OrganizationComponent *)department_composite_constructor("总裁办");
  9.    OrganizationComponent *com2 = (OrganizationComponent *)department_composite_constructor("行动队");
  10.    OrganizationComponent *com3 = (OrganizationComponent *)department_composite_constructor("后勤组");
  11.    OrganizationComponent *leaf1 = (OrganizationComponent *)employee_leaf_constructor("唐三藏");
  12.    OrganizationComponent *leaf2 = (OrganizationComponent *)employee_leaf_constructor("孙悟空");
  13.    OrganizationComponent *leaf3 = (OrganizationComponent *)employee_leaf_constructor("猪悟能");
  14.    OrganizationComponent *leaf4 = (OrganizationComponent *)employee_leaf_constructor("沙悟净");
  15.    com->add(com, com1);
  16.    com->add(com, com2);
  17.    com->add(com, com3);
  18.    // leaf1属于com1
  19.    com1->add(com1, leaf1);
  20.    // leaf2, leaf3属于com2
  21.    com2->add(com2, leaf2);
  22.    com2->add(com2, leaf3);
  23.    // 添加再删除
  24.    DepartmentComposite *dept1 = department_composite_constructor("小分队");
  25.    com2->add(com2, (OrganizationComponent *)dept1);
  26.    EmployeeLeaf *tmp1 = employee_leaf_constructor("临时工");
  27.    dept1->add((OrganizationComponent *)dept1, (OrganizationComponent *)tmp1);
  28.    dept1->remove((OrganizationComponent *)dept1, (OrganizationComponent *)tmp1);
  29.    // leaf4属于com3
  30.    com3->add(com3, leaf4);
  31.    // 执行全部节点动作
  32.    com->operation(com);
  33.    // 获取某个节点
  34.    OrganizationComponent *dept2 = com->get_child(com, 1);
  35.    EmployeeLeaf *employee_child1 = (EmployeeLeaf *)dept2->get_child(dept2, 0);
  36.    printf("\r\n [employee->name=%s]", employee_child1->name);
复制代码
 
更多语言版本

不同语言实现设计模式源码,请查看:https://github.com/microwind/design-pattern

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册