文本是《设计模式(共12篇)》专题的第 10 篇。阅读本文前,建议先阅读前面的文章:
组合模式详解
1️⃣ 概念
定义: 将对象组合成树形结构以表示"部分-整体"的层次结构;组合模式使客户端对单个对象和组合对象保持一致的方式处理。
类型: 结构性
2️⃣ 适用场景
- 希望客户端可以忽略组合对象与单个对象的差异时
 - 处理一个树形结构时
 
3️⃣ 优点
- 清楚的定义分层次的复杂对象,表示对象的全部或部分层次
 - 让客户端忽略了层次的差异,方便对整个层次结构进行控制
 - 简化客户端代码
 - 符合开闭原则
 
4️⃣ 缺点
- 限制类型时会比较复杂
 - 使设计变的更加抽象
 
5️⃣ 组合模式Coding
① 创建CatalogComponent类
from abc import ABC, abstractmethod
from typing import List
class CatalogComponent(ABC):
    def add(self, catalog_component):
        raise NotImplementedError("不支持添加操作")
    def remove(self, catalog_component):
        raise NotImplementedError("不支持删除操作")
    def get_name(self):
        raise NotImplementedError("不支持获取名称操作")
    def get_price(self):
        raise NotImplementedError("不支持获取价格操作")
    def print(self):
        raise NotImplementedError("不支持打印操作")
② 创建Course类继承CatalogComponent类
class Course(CatalogComponent):
    def __init__(self, name: str, price: float):
        self.name = name
        self.price = price
    def get_name(self):
        return self.name
    def get_price(self):
        return self.price
    def print(self):
        print(f"Course Name:{self.name} Price:{self.price}")
③ 创建CourseCatalog类继承CatalogComponent类
class CourseCatalog(CatalogComponent):
    def __init__(self, name: str, level: int):
        self.items: List[CatalogComponent] = []
        self.name = name
        self.level = level
    def add(self, catalog_component: CatalogComponent):
        self.items.append(catalog_component)
    def get_name(self):
        return self.name
    def remove(self, catalog_component: CatalogComponent):
        if catalog_component in self.items:
            self.items.remove(catalog_component)
    def print(self):
        print(self.name)
        for catalog_component in self.items:
            if self.level is not None:
                for i in range(self.level):
                    print("  ", end="")
            catalog_component.print()
④ 编写测试代码
def main():
    linux_course = Course("Linux课程", 11)
    windows_course = Course("Windows课程", 11)
    python_course_catalog = CourseCatalog("Python课程目录", 2)
    mmall_course1 = Course("Python电商一期", 55)
    mmall_course2 = Course("Python电商二期", 66)
    design_pattern = Course("Python设计模式", 77)
    python_course_catalog.add(mmall_course1)
    python_course_catalog.add(mmall_course2)
    python_course_catalog.add(design_pattern)
    imooc_main_course_catalog = CourseCatalog("课程主目录", 1)
    imooc_main_course_catalog.add(linux_course)
    imooc_main_course_catalog.add(windows_course)
    imooc_main_course_catalog.add(python_course_catalog)
    imooc_main_course_catalog.print()
if __name__ == "__main__":
    main()
运行结果:
课程主目录
  Linux课程 Price:11
  Windows课程 Price:11
  Python课程目录
    Python电商一期 Price:55
    Python电商二期 Price:66
    Python设计模式 Price:77
6️⃣ 组合模式的实际应用
Python GUI框架 tkinter
tkinter中的Widget类就是一个很好的组合模式例子,Container类可以包含其他Widget,而Leaf Widget(如Button、Label)则是叶子节点。
import tkinter as tk
# 示例:Frame可以包含其他组件,体现了组合模式
root = tk.Tk()
frame = tk.Frame(root)  # 组合对象
button = tk.Button(frame, text="Click")  # 叶子对象
label = tk.Label(frame, text="Hello")    # 叶子对象
Python collections.abc
Python的collections.abc模块中的Container、Iterable等抽象基类也体现了组合模式的思想。
Django模型继承
Django的模型继承和组合也是组合模式的实际应用:
from django.db import models
class Component(models.Model):
    name = models.CharField(max_length=100)
    class Meta:
        abstract = True
class Leaf(Component):
    value = models.CharField(max_length=100)
class Composite(Component):
    children = models.ManyToManyField('self', blank=True)
您已阅读完《设计模式(共12篇)》专题的第 10 篇。请继续阅读该专题下面的文章:
