谷动谷力
标题:
【C语言】用C语言实现组合模式
[打印本页]
作者:
鸣涧
时间:
2023-9-20 13:54
标题:
【C语言】用C语言实现组合模式
【C语言】用C语言实现组合模式
组合模式,又称为部分-整体模式,是一种结构型设计模式。是针对由多个节点对象(部分)组合而成的树形结构的对象(整体)的设计模式。这种设计模式抽象并统一了简单元素和复杂元素的概念,这样客户端能够使用统一的方法操作整体对象或者其下的每一个节点部分对象。客户端不用关注对象内部的组织结构,是整体的,还是部分的,从而做到客户端与具有复杂层次结构的对象解耦。
组合模式能够优化处理递归或分级数据结构,将树形结构特点发挥的淋漓尽致,作为最高级抽象的抽象节点类(接口)泛化了所有节点类,使任何整体或者部分达到统一,根、枝与叶节点的多态化实现及组合关系进一步形成树形结构。通过用户操作,由根到枝再到叶,逐级递归,自动生成。接下来看一下组合模式的类结构:
组合模式中各角色的定义如下:
Component(组件接口):所有复合组件(节点)与叶组件(节点)的高层抽象,定义出需要对组件操作的接口标准。
Composite(复合组件):包含多个子组件对象(可以是复合组件或叶端组件)的复合型组件,并实现组件接口中定义的操作方法。
Leaf(叶端组件):不包含子组件的终端组件,同样实现组件接口中定义的操作方法。
Client(客户端):按所需的层级关系部署相关对象,并操作组件接口所定义的接口,即可遍历树结构上的所有组件。
在设计组合模式时,需要注意如下几点:
理清部分与整体对象的关系,了解对象的组成结构。
组合模式是一种具有清晰的层次关系的树形结构,不能再分的叶子节点是具体的组件,也是最小的逻辑单元;具有子节点或有多个子组件组成的组件是符合组件。
组合模式也有优缺点,接下来看一下他的优缺点:
组合模式的优点:
调用比较简单,组合对象可以像一般对象使用。
组合对象可以灵活地组合不同的对象,比如自由地增加、删除组件。
组合模式的缺点;
在一些层次结构深的场景中,组合结构会变得太庞杂。
2,举例
#include <stdio.h>
<p></p><p>#include <stdlib.h></p><p>
</p><p>enum type{</p><p> LEAF = 1,</p><p> BRANCH,</p><p>};</p><p>// 定义组件接口</p><p>typedef struct Component {</p><p> int value;</p><p> int type;</p><p> void (*operation)(struct Component *);</p><p>} Component;</p><p>
</p><p>// 定义叶子节点</p><p>typedef struct Leaf {</p><p> Component base;</p><p>} Leaf;</p><p>
</p><p>void leaf_operation(Component *component) {</p><p> printf("Leaf: %d\n", component->value);</p><p>}</p><p>
</p><p>Leaf* leaf_create(int value) {</p><p> Leaf *leaf = (Leaf*)malloc(sizeof(Leaf));</p><p> leaf->base.value = value;</p><p> leaf->base.type = LEAF;</p><p> leaf->base.operation = leaf_operation;</p><p> return leaf;</p><p>}</p><p>
</p><p>// 定义组合节点</p><p>typedef struct Composite {</p><p> Component base;</p><p> Component **children;</p><p> int num_children;</p><p>} Composite;</p><p>
</p><p>#define offsetof(s, m) ((size_t)&(((s *)0)->m))</p><p>#define container_of(ptr, type, member) \</p><p> ((type *)((char *)(ptr) - offsetof(type, member)))</p><p>
</p><p>void composite_operation(Component *component) {</p><p> Composite *composite = (Composite*)component;</p><p> printf("Composite: %d\n", component->value);</p><p>
</p><p> for (int i = 0; i < composite->num_children; i++) {</p><p> composite->children[i]->operation(composite->children[i]);</p><p> }</p><p>}</p><p>
</p><p>Composite* composite_create(int value, int num_children) {</p><p> Composite *composite = (Composite*)malloc(sizeof(Composite));</p><p> composite->base.value = value;</p><p> composite->base.type = BRANCH;</p><p> composite->base.operation = composite_operation;</p><p> composite->num_children = num_children;</p><p> composite->children = (Component**)malloc(sizeof(Component*) * num_children);</p><p> for (int i = 0; i < num_children; i++) {</p><p> composite->children[i] = NULL;</p><p> }</p><p> return composite;</p><p>}</p><p>
</p><p>void composite_add_child(Composite *composite, Component *child, int index) {</p><p> if (index < 0 || index >= composite->num_children) {</p><p> printf("Invalid index %d\n", index);</p><p> return;</p><p> }</p><p> composite->children[index] = child;</p><p>}</p><p>
</p><p>void composite_remove_child(Composite *composite, int index) {</p><p> if (index < 0 || index >= composite->num_children) {</p><p> printf("Invalid index %d\n", index);</p><p> return;</p><p> }</p><p> composite->children[index] = NULL;</p><p>}</p><p>
</p><p>void composite_free_unit(Composite *composite) {</p><p> if (!composite)</p><p> return;</p><p>
</p><p> if (composite->base.type == LEAF)</p><p> return;</p><p>
</p><p> for (int i = 0; i < composite->num_children; i++) {</p><p> if (composite->children[i]) {</p><p> composite_free_unit((struct Composite*)container_of(composite->children[i], struct Composite, base));</p><p> printf("free children[%d], value: %d\n", i, composite->children[i]->value);</p><p> free(composite->children[i]);</p><p> }</p><p> }</p><p>
</p><p> if (composite->children) {</p><p> free(composite->children);</p><p> }</p><p>}</p><p>
</p><p>void composite_free(Composite *composite) {</p><p> composite_free_unit(composite);</p><p> if (composite) {</p><p> free(composite);</p><p> }</p><p>}</p><p>int main() {</p><p> printf("create root and leaf\n");</p><p> // 创建根节点和叶子节点</p><p> Composite *root = composite_create(0, 3);</p><p> Leaf *leaf1 = leaf_create(1);</p><p> Leaf *leaf2 = leaf_create(2);</p><p>
</p><p> // 将叶子节点添加到根节点中</p><p> composite_add_child(root, &leaf1->base, 0);</p><p> composite_add_child(root, &leaf2->base, 1);</p><p>
</p><p> // 创建子节点并将其添加到根节点中</p><p> Composite *subtree = composite_create(3, 2);</p><p> Leaf *leaf3 = leaf_create(4);</p><p> Leaf *leaf4 = leaf_create(5);</p><p> composite_add_child(subtree, &leaf3->base, 0);</p><p> composite_add_child(subtree, &leaf4->base, 1);</p><p> composite_add_child(root, &subtree->base, 2);</p><p>
</p><p> // 执行操作</p><p> root->base.operation(&root->base);</p><p>
</p><p> printf("free root and leaf\n");</p><p> // 释放内存</p><p> composite_free(root);</p><p>
</p><p> return 0;</p><p>}</p>
复制代码
在例子中,定义了一个 Component 接口作为组件的抽象基类,其中包含了 value 属性,type属性和一个指向 operation 函数的指针。这样我们就可以将 Leaf 和 Composite 分别作为叶子节点和组合节点来实现组合模式,并在它们的构造函数中初始化 Component 的共同成员。
还定义了一些工具函数来操作组合节点的子节点,如 composite_add_child 和 composite_remove_child 等。此外,还使用了 malloc 和 free 函数来动态分配和释放内存,避免出现内存泄漏等问题。
最后,客户端通过创建根节点和一些子节点来构建一个包含多层嵌套关系的树形结构,并在根节点上调用 operation 函数,实现了对整棵树的遍历和处理。
欢迎光临 谷动谷力 (http://bbs.sunsili.com/)
Powered by Discuz! X3.2