设计模式Python版 组合模式

文章目录


前言

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 NotImplementedError

    def remove(self, file):
        raise NotImplementedError

    def kill_virus(self):
        raise NotImplementedError


"""容器构件"""


class Folder(AbstracFile):
    def __init__(self, name):
        self.name = name
        self.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 = name

    def kill_virus(self):
        # 模拟杀毒
        print(f"------对图像文件 {self.name} 进行杀毒")


class TextFile(AbstracFile):
    def __init__(self, name):
        self.name = name

    def kill_virus(self):
        # 模拟杀毒
        print(f"------对文本文件 {self.name} 进行杀毒")


class VideoFile(AbstracFile):
    def __init__(self, name):
        self.name = name

    def 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()

输出结果

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

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

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


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

相关推荐
try2find1 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取2 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
缘来是庄3 小时前
设计模式之建造者模式
java·设计模式·建造者模式
精灵vector3 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习4 小时前
Python入门Day2
开发语言·python
Vertira4 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉4 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗4 小时前
黑马python(二十四)
开发语言·python
晓13135 小时前
OpenCV篇——项目(二)OCR文档扫描
人工智能·python·opencv·pycharm·ocr
是小王同学啊~5 小时前
(LangChain)RAG系统链路向量检索器之Retrievers(五)
python·算法·langchain