一、说明
组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。
(一) 解决问题
- 处理树形结构:可以很好地处理树形结构的数据,使得用户可以统一对待单个对象和对象组合。
- 统一接口:可以通过统一的接口来操作单个对象和对象组合,简化了客户端的代码。
- 递归组合:可以通过递归的方式来处理对象组合,使得代码更加灵活。
(二) 使用场景
- 需要实现树状对象结构
- 希望客户端以相同的方式处理简单和复杂元素
二、结构
- 组件(Component)接口描述了树中简单项目和复杂项目所共有的操作。
- 叶节点(Leaf)是树的基本结构,它不包含子项目。一般情况下,叶节点最终会完成大部分的实际工作,因为它们无法将工作指派给其他部分。
- 容器(Container)——又名 “组合 (Composite)”——是包含叶节点或其他容器等子项目的单位。容器不知道其子项目所属的具体类,它只通过通用的组件接口与其子项目交互。容器接收到请求后会将工作分配给自己的子项目,处理中间结果,然后将最终结果返回给客户端。
- 客户端(Client)通过组件接口与所有项目交互。因此,客户端能以相同方式与树状结构中的简单或复杂项目交互。
三、伪代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__doc__ = """
组合模式
例:生成具有树状结构的食品分类,并遍历输出
"""
from abc import ABC, abstractmethod
class Component(ABC):
"""抽象基类"""
@abstractmethod
def operation(self):
pass
class Leaf(Component):
"""叶子节点类"""
def __init__(self, name):
self.name = name
def operation(self, indent=""):
return f"{indent}- {self.name}"
class Composite(Component):
"""容器节点类"""
def __init__(self, name):
self.name = name
self.children = []
def add(self, component):
self.children.append(component)
def remove(self, component):
self.children.remove(component)
def operation(self, indent=""):
result = [f"{indent}+ {self.name}"]
for child in self.children:
result.append(child.operation(indent + " "))
return "\n".join(result)
if __name__ == "__main__":
"""
+ 食品
+ 水果
- 苹果
- 香蕉
+ 蔬菜
- 西红柿
- 黄瓜
"""
fruit = Composite("水果")
fruit.add(Leaf("苹果"))
fruit.add(Leaf("香蕉"))
vegetable = Composite("蔬菜")
vegetable.add(Leaf("西红柿"))
vegetable.add(Leaf("黄瓜"))
food = Composite("食品")
food.add(fruit)
food.add(vegetable)
print(food.operation())
四、优缺点
优点
- 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
缺点
- 对于功能差异较大的类,提供公共接口或许会有困难。在特定情况下,你需要过度一般化组件接口,使其变得令人难以理解。