文本是《设计模式(共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 篇。请继续阅读该专题下面的文章:
