设计模式Python版 组合模式

embedded/2025/2/3 1:24:26/

文章目录


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、组合模式

组合模式(Composite Pattern)

  • 定义:组合多个对象形成树形结构以表示具有“部分—整体”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,又可以称为“部分—整体”(Part-Whole)模式。

  • 解决问题:如何使用面向对象的方式来处理软件系统中的树形结构?

  • 使用场景:

    • 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致性地对待它们。
    • 在一个使用面向对象语言开发的系统中需要处理一个树形结构。
    • 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,将来需要增加一些新的类型。
    • 在XML解析、组织结构树处理、文件系统设计等领域,组合模式都得到了广泛应用。
  • 组成:

    • 抽象构件(Component):它是所有容器类和叶子类的公共父类,为叶子构件和容器构件对象声明接口。一般将抽象构件类设计为接口或抽象类,将所有子类共有方法的声明和实现放在抽象构件类中。对于客户端而言,将针对抽象构件编程,而无须关心其具体子类是容器构件还是叶子构件。
    • 叶子构件(Leaf):代表组合结构中的叶节点对象,叶节点对象不再包含子节点。
    • 容器构件(Composite):它在组合模式结构中表示容器节点对象。容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点。用列表实现容器构件
  • 补充说明

    • 组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器。客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。
    • 容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。
  • 优点:

    • 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次。客户端无须关心节点的层次结构,可以对所选节点进行统一处理,提高系统的灵活性。
    • 将容器对象和叶子对象进行递归组合,实现简单,灵活性好,使用频率较高。
    • 组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合开闭原则。
    • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案。
  • 缺点:

    • 在增加新构件时很难对容器中的构件类型进行限制。

二、组合模式实现方式

实现方式一:透明组合模式

  • 根据抽象构件类的定义形式,可将组合模式分为透明组合模式和安全组合模式两种形式。
  • 抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法
  • 透明组合模式结构图

在这里插入图片描述

实现方式二:安全组合模式

  • 抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。
  • 安全组合模式结构图

在这里插入图片描述

三、组合模式示例

使用透明组合模式来进行杀毒软件的框架设计

  • AbstractFile充当抽象构件类,Folder充当容器构件类,ImageFile、TextFile和VideoFile充当叶子构件类
python">"""抽象构件"""class AbstracFile:def add(self, file):raise NotImplementedErrordef remove(self, file):raise NotImplementedErrordef kill_virus(self):raise NotImplementedError"""容器构件"""class Folder(AbstracFile):def __init__(self, name):self.name = nameself.file_list: list[AbstracFile] = []def add(self, file):self.file_list.append(file)def remove(self, file):if file in self.file_list:self.file_list.remove(file)def kill_virus(self):# 模拟杀毒print(f"——对文件夹 {self.name} 进行杀毒")# 循环调用成员构件的业务方法for i in self.file_list:i.kill_virus()"""叶子构件"""class ImageFile(AbstracFile):def __init__(self, name):self.name = namedef kill_virus(self):# 模拟杀毒print(f"——对图像文件 {self.name} 进行杀毒")class TextFile(AbstracFile):def __init__(self, name):self.name = namedef kill_virus(self):# 模拟杀毒print(f"——对文本文件 {self.name} 进行杀毒")class VideoFile(AbstracFile):def __init__(self, name):self.name = namedef kill_virus(self):# 模拟杀毒print(f"——对视频文件 {self.name} 进行杀毒")

客户端代码

python"># 针对抽象构件编程
folder1 = Folder("张三的资料")
folder2 = Folder("图像文件")
folder3 = Folder("文本文件")
folder4 = Folder("视频文件")file1 = ImageFile("《洛神赋图》.gif")
file2 = ImageFile("《清明上河图》.jpg")
file3 = TextFile("《分析与设计》.txt")
file4 = TextFile("《设计模式》.doc")
file5 = VideoFile("《西游记》.rmvb")folder2.add(file1)
folder2.add(file2)
folder3.add(file3)
folder3.add(file4)
folder4.add(file5)
folder1.add(folder2)
folder1.add(folder3)
folder1.add(folder4)folder1.kill_virus()
# 也可以创建图形化界面让用户选择所需操作的根节点,无须修改源代码,符合开闭原则。
# folder2.kill_virus()

输出结果

——对文件夹 张三的资料 进行杀毒
——对文件夹 图像文件 进行杀毒
——对图像文件 《洛神赋图》.gif 进行杀毒   
——对图像文件 《清明上河图》.jpg 进行杀毒 
——对文件夹 文本文件 进行杀毒
——对文本文件 《分析与设计》.txt 进行杀毒 
——对文本文件 《设计模式》.doc 进行杀毒   
——对文件夹 视频文件 进行杀毒
——对视频文件 《西游记》.rmvb 进行杀毒  

四、组合模式在Django中的应用

Django 的 admin 界面允许用户以树形结构来组织模型。例如,一个 Group 可以包含多个 User,而 User 又可以属于多个 Group。在 admin 界面中,这种关系可以用组合模式来实现,其中 Group 可以看作是组合对象,而 User 可以看作是叶节点。

在这里插入图片描述


您正在阅读的是《设计模式Python版》专栏!关注不迷路~


http://www.ppmy.cn/embedded/159052.html

相关文章

【C++】特殊类设计

目录 一、请设计一个类,不能被拷贝二、请设计一个类,只能在堆上创建对象三、请设计一个类,只能在栈上创建对象四、请设计一个类,不能被继承五、请设计一个类,只能创建一个对象(单例模式)5.1 饿汉模式5.2 懒汉模式 结尾…

四.3 Redis 五大数据类型/结构的详细说明/详细使用( hash 哈希表数据类型详解和使用)

四.3 Redis 五大数据类型/结构的详细说明/详细使用( hash 哈希表数据类型详解和使用) 文章目录 四.3 Redis 五大数据类型/结构的详细说明/详细使用( hash 哈希表数据类型详解和使用)2.hash 哈希表常用指令(详细讲解说明)2.1 hset …

javascript-es6 (一)

作用域(scope) 规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问 局部作用域 函数作用域: 在函数内部声明的变量只能在函数内部被访问,外部无法直接访问 function getSum(){ //函数内部是函数作用…

OpenCV边沿检测(Python版)

边缘检测是图像处理中的一项重要任务,用于找到图像中的边界或边缘。它在计算机视觉、图像处理和模式识别等领域中具有广泛的应用。 边缘可以被定义为图像亮度、颜色或纹理的突变区域。边缘检测算法旨在识别这些变化并将其标记为边缘。边缘检测可以用于分割图像、检测…

【4Day创客实践入门教程】Day2 探秘微控制器——单片机与MicroPython初步

Day2 探秘微控制器——单片机与MicroPython初步 目录 Day2 探秘微控制器——单片机与MicroPython初步MicroPython语言基础开始基础语法注释与输出变量模块与函数 单片机基础后记 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机…

嵌入式硬件篇---CPUGPUTPU

文章目录 第一部分:处理器CPU(中央处理器)1.通用性2.核心数3.缓存4.指令集5.功耗和发热 GPU(图形处理器)1.并行处理2.核心数量3.内存带宽4.专门的应用 TPU(张量处理单元)1.为深度学习定制2.低精…

SpringBoot 中的测试jar包knife4j(实现效果非常简单)

1、效果图 非常快的可以看见你实现的接口 路径http://localhost:8080/doc.html#/home 端口必须是自己的 2、实现效果 2.1、导入jar包 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-star…

【leetcode】T541 (两点反思)

解题反思 闷着头往&#xff0c;往往会写成一团浆糊&#xff0c;还推倒重来&#xff0c;谋划好全局思路再开始很重要。 熟悉C的工具库很重要&#xff0c;一开始看到反转就还想着用stack来着&#xff0c;后面突然想起来用reverse函数刚好可以用哇&#xff0c;这题也就迎刃而解了…