【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)

server/2024/11/27 14:21:42/

1. 设计模式原理说明

组合模式(Composite Pattern) 是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性。这意味着无论处理的是单一对象还是复合对象,都可以使用相同的接口进行操作。

主要角色
  1. Component(组件):定义了树中每个对象的接口,可以是叶子节点或容器节点。
  2. Leaf(叶子节点):表示树中的末端节点,没有子节点,实现 Component 接口的具体行为。
  3. Composite(容器节点):表示树中的分支节点,可以包含一个或多个子节点,实现了 Component 接口的行为,并负责管理子节点的添加、删除等操作。
  4. Client(客户端):通过 Component 接口与所有对象交互,无需关心对象是叶子节点还是容器节点。

2. UML 类图及解释

UML 类图
+-----------------+                +-----------------+
|    Component    |                |      Leaf       |
|-----------------|                |-----------------|
| + operation(): void|             | + operation(): void|
+-----------------+                +-----------------+^                             ^|                             ||                             |v                             v
+-----------------+
|   Composite     |
|-----------------|
| - children: List<Component>  |
| + add(child: Component): void|
| + remove(child: Component): void|
| + getChild(index: int): Component|
| + operation(): void            |
+-----------------+
类图解释
  • Component:定义了树中每个对象的接口,可以是叶子节点或容器节点。客户端通过这个接口与所有对象交互。
  • Leaf:表示树中的末端节点,没有子节点,实现 Component 接口的具体行为。
  • Composite:表示树中的分支节点,可以包含一个或多个子节点,实现了 Component 接口的行为,并负责管理子节点的添加、删除等操作。
  • Client:通过 Component 接口与所有对象交互,无需关心对象是叶子节点还是容器节点。

3. 代码案例及逻辑详解

Java 代码案例
// 组件接口
interface Component {void operation();
}// 叶子节点
class Leaf implements Component {@Overridepublic void operation() {System.out.println("Leaf operation");}
}// 容器节点
class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}public Component getChild(int index) {return children.get(index);}@Overridepublic void operation() {for (Component child : children) {child.operation();}}
}// 客户端
public class Client {public static void main(String[] args) {Composite root = new Composite();Composite branch = new Composite();Leaf leaf1 = new Leaf();Leaf leaf2 = new Leaf();branch.add(leaf1);branch.add(leaf2);root.add(branch);root.operation();// 输出:// Leaf operation// Leaf operation}
}
C++ 代码案例
#include <iostream>
#include <vector>// 组件接口
class Component {
public:virtual void operation() = 0;virtual ~Component() {}
};// 叶子节点
class Leaf : public Component {
public:void operation() override {std::cout << "Leaf operation" << std::endl;}
};// 容器节点
class Composite : public Component {
private:std::vector<Component*> children;public:void add(Component* component) {children.push_back(component);}void remove(Component* component) {children.erase(std::remove(children.begin(), children.end(), component), children.end());}Component* getChild(int index) {return children[index];}void operation() override {for (Component* child : children) {child->operation();}}~Composite() {for (Component* child : children) {delete child;}}
};// 客户端
int main() {Composite* root = new Composite();Composite* branch = new Composite();Leaf* leaf1 = new Leaf();Leaf* leaf2 = new Leaf();branch->add(leaf1);branch->add(leaf2);root->add(branch);root->operation();// 输出:// Leaf operation// Leaf operationdelete root;return 0;
}
Python 代码案例
from abc import ABC, abstractmethod
from typing import List# 组件接口
class Component(ABC):@abstractmethoddef operation(self):pass# 叶子节点
class Leaf(Component):def operation(self):print("Leaf operation")# 容器节点
class Composite(Component):def __init__(self):self.children: List[Component] = []def add(self, component: Component):self.children.append(component)def remove(self, component: Component):self.children.remove(component)def get_child(self, index: int) -> Component:return self.children[index]def operation(self):for child in self.children:child.operation()# 客户端
if __name__ == "__main__":root = Composite()branch = Composite()leaf1 = Leaf()leaf2 = Leaf()branch.add(leaf1)branch.add(leaf2)root.add(branch)root.operation()# 输出:# Leaf operation# Leaf operation
Go 代码案例
package mainimport "fmt"// 组件接口
type Component interface {Operation()
}// 叶子节点
type Leaf struct{}func (l *Leaf) Operation() {fmt.Println("Leaf operation")
}// 容器节点
type Composite struct {children []Component
}func (c *Composite) Add(child Component) {c.children = append(c.children, child)
}func (c *Composite) Remove(child Component) {for i, ch := range c.children {if ch == child {c.children = append(c.children[:i], c.children[i+1:]...)break}}
}func (c *Composite) GetChild(index int) Component {return c.children[index]
}func (c *Composite) Operation() {for _, child := range c.children {child.Operation()}
}// 客户端
func main() {root := &Composite{}branch := &Composite{}leaf1 := &Leaf{}leaf2 := &Leaf{}branch.Add(leaf1)branch.Add(leaf2)root.Add(branch)root.Operation()// 输出:// Leaf operation// Leaf operation
}

4. 总结

组合模式 是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性,从而提高了系统的灵活性和可扩展性。

主要优点
  1. 一致性:用户可以通过相同的接口操作单个对象和组合对象,使得客户端代码更加简洁和一致。
  2. 灵活性组合模式使得树形结构的构建更加灵活,可以动态地添加和删除节点。
  3. 易于扩展:新增节点类型时,只需实现 Component 接口即可,无需修改现有代码。
主要缺点
  1. 增加了系统的复杂性组合模式引入了更多的类和接口,增加了系统的复杂性。
  2. 客户端需要谨慎处理空指针:如果客户端代码不小心访问了空指针,可能会导致运行时错误。
适用场景
  • 当需要表示部分-整体层次结构时。
  • 当希望用户可以忽略组合对象与单个对象的不同,统一使用组合结构中的所有对象。
  • 当系统中存在复杂的树形结构,需要频繁地添加、删除节点时。

http://www.ppmy.cn/server/145351.html

相关文章

基于RDKit的分子描述符分析与特征选择:以溶解度预测为例

基于RDKit的分子描述符分析与特征选择&#xff1a;以溶解度预测为例 在药物化学、材料科学和环境化学等领域&#xff0c;分子特性与其生物活性或环境行为之间的关系&#xff08;例如溶解度、毒性等&#xff09;是至关重要的。定量构效关系&#xff08;QSAR&#xff09;建模可以…

Stable Diffusion中的自注意力替换技术与Diffusers实现

Stable Diffusion中的自注意力替换技术与Diffusers实现 文章目录 Stable Diffusion中的自注意力替换技术与Diffusers实现摘要Abstract一、机器学习部分1. 注意力计算2. SD中的自注意力替换3. 自注意力替换的应用4. 在 Diffusers 里实现自注意力替换4.1 AttentionProcessor4.2 实…

前端 Vue 3 后端 Node.js 和Express 结合cursor常见提示词结构

cursor 提示词 后端提示词 请为我开发一个基于 Node.js 和Express 框架的 Todo List 后端项目。项目需要实现以下四个 RESTful API 接口&#xff1a; 查询所有待办事项 接口名: GET /api/get-todo功能: 从数据库的’list’集合中查询并返回所有待办事项参数: 无返回: 包含所…

分类算法——基于heart数据集实现

1 heart数据集——描述性统计分析 import matplotlib.pyplot as plt import pandas as pd# Load the dataset heart pd.read_csv(r"heart.csv", sep,)# Check the columns in the DataFrame print(heart.columns)aheart.loc[:, y].value_counts() print(a) heart.l…

【linux】线程概念与控制

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 线程基本概念 &#x1f98b; 1-1 什么是线程&#x1f98b; 1-2 分⻚式存储管理1-2-1 虚拟地址和⻚表的由来1-2-2 ⻚表1-2-3 ⻚⽬录结构1-2-4 两级⻚表的地…

uname -m(machine) 命令用于显示当前系统的机器硬件架构(Unix Name)

文章目录 关于 arm64 架构检查是否安装了 Rosetta 2其他相关信息解释&#xff1a;命令功能&#xff1a;示例&#xff1a; dgqdgqdeMac-mini / % uname -m arm64您运行的 uname -m 命令显示您的系统架构是 arm64。这意味着您的 Mac Mini 使用的是 Apple 的 M1 或更新的芯片&…

Java与C#

Java和C#&#xff08;C Sharp&#xff09;是两种流行的面向对象编程语言&#xff0c;它们在很多方面非常相似&#xff0c;因为它们都受到了类似的编程范式和语言设计理念的影响。然而&#xff0c;它们之间也存在一些重要的区别。 平台依赖性&#xff1a; Java&#xff1a;Java是…

sql漏洞

目录 SQL漏洞产生的原因 未对用户输入进行验证和过滤&#xff1a; 动态SQL语句的拼接&#xff1a; 不安全的数据库配置&#xff1a; 缺乏安全意识和培训&#xff1a; 使用过时的技术或框架&#xff1a; 如何避免SQL漏洞产生 使用参数化查询&#xff1a; 对用户输入进行…