当前位置: 首页 > article >正文

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

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 {
    @Override
    public 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);
    }

    @Override
    public 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 operation

    delete root;

    return 0;
}
Python 代码案例
from abc import ABC, abstractmethod
from typing import List

# 组件接口
class Component(ABC):
    @abstractmethod
    def 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 main

import "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.kler.cn/a/411012.html

相关文章:

  • Qt SQL模块概述
  • 【前端】ES6基础
  • 【C++ 算法进阶】算法提升二十三
  • 【深度学习】【RKNN】【C++】模型转化、环境搭建以及模型部署的详细教程
  • 40分钟学 Go 语言高并发:【实战】并发安全的配置管理器(功能扩展)
  • C++语言之函数对象与算法
  • HOW - React 状态模块化管理和按需加载(二) - jotai
  • Java ArrayList 与顺序表:在编程海洋中把握数据结构的关键之锚
  • Java学习笔记--继承的介绍,基本使用,成员变量和成员方法访问特点
  • MySQL 与 MongoDB 存储差异分析
  • 【优先算法学习】双指针--结合题目讲解学习
  • 深入了解决策树---机器学习中的经典算法
  • 排除杂音噪音,手机录音去除杂音软件如何办到?
  • vscode 如何鼠标双击时选择带有-的
  • 【北京迅为】iTOP-4412全能版使用手册-第十一章 设备树Linux系统编译
  • uniapp 开发微信小程序笔记
  • 计算机网络----基本概念
  • 华为云开发的入门介绍
  • 相亲交友小程序项目介绍
  • 【在Linux世界中追寻伟大的One Piece】多线程(二)
  • 文件上传upload-labs-docker通关
  • C++初阶—C++入门
  • 【算法】连通块问题(C/C++)
  • Qt常用控件之按钮类控件
  • 微前端基础知识入门篇(二)
  • PPT中插入Latex公式