1. 组合模式简介
组合模式(Composite Pattern)用于将对象组合成树形结构以表示部分-整体的层次结构。这种模式使得用户对单个对象和组合对象的使用具有一致性。
2. 用一个常见的例子来理解组合模式:文件系统
让我们以文件系统为例来演示组合模式。在文件系统中,目录和文件可以被看作是树形结构中的节点,目录可以包含其他目录和文件,因此可以使用组合模式来表示文件系统的层次结构。
下面是对应的 Python 代码:
from abc import ABC, abstractmethod
# Component: 抽象基类
class FileSystemComponent(ABC):
@abstractmethod
def display(self):
pass
# Leaf: 叶子节点(文件)
class File(FileSystemComponent):
def __init__(self, name):
self.name = name
def display(self):
print(f"File: {self.name}")
# Composite: 组合节点(目录)
class Directory(FileSystemComponent):
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 display(self):
print(f"Directory: {self.name}")
for child in self.children:
child.display()
# 客户端代码
if __name__ == "__main__":
# 创建文件
file1 = File("file1.txt")
file2 = File("file2.txt")
# 创建目录
directory1 = Directory("dir1")
directory2 = Directory("dir2")
# 向目录添加文件
directory1.add(file1)
directory2.add(file2)
# 创建更高层级的目录,并将之前的目录添加到其中
directory = Directory("root")
directory.add(directory1)
directory.add(directory2)
# 打印整个文件系统的层次结构
directory.display()
在上面的示例中,FileSystemComponent 是抽象基类,定义了组合模式中的组件接口。File 是叶子节点类,表示文件。Directory 是组合节点类,表示目录,可以包含其他目录和文件。在客户端代码中,我们创建了文件和目录,并通过 add() 方法将它们组合在一起形成文件系统的层次结构,然后通过 display() 方法打印出整个文件系统的层次结构。
3. 组合模式的结构
组合模式的典型结构如下图所示:
它包含以下几个实体:
-
Component(组件) : 定义组合中的对象的接口,可以是抽象类或接口,并声明了组合中所有对象的默认行为。在组合模式中,所有的叶子节点和组合节点都必须实现这个接口。
-
Leaf(叶子节点) : 表示组合中的叶子节点对象,它没有子节点。叶子节点实现了组件接口,并定义了叶子对象的行为。
-
Composite(组合节点) : 表示组合中的组合节点对象,它有子节点。组合节点实现了组件接口,并提供了管理子节点的方法,如添加、删除子节点等。
-
Client (客户端) : 通过组件接口与所有项目交互。 因此, 客户端能以相同方式与树状结构中的简单或复杂项目交互。
4. 简单练习:【设计模式专题之组合模式】11-公司组织架构
"""
【设计模式专题之组合模式】11-公司组织架构
时间限制:1.000S 空间限制:256MB
题目描述
小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。
请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。
输入描述
第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。
接下来的 N 行,每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。
输出描述
输出公司的组织结构,展示每个部门下的子部门和员工
输入示例
MyCompany
8
D HR
E HRManager
D Finance
E AccountantA
E AccountantB
D IT
E DeveloperA
E DeveloperB
输出示例
Company Structure:
MyCompany
HR
HRManager
Finance
AccountantA
AccountantB
IT
DeveloperA
DeveloperB
"""
from abc import ABC, abstractmethod
class Member(ABC):
@abstractmethod
def show(self, level: int):
raise NotImplemented
class Employee(Member):
def __init__(self, name: str):
self.name = name
def show(self, level: int):
indent = " " * level
print(indent + " " + self.name)
class Department(Member):
def __init__(self, name: str):
self.name = name
self.children = []
def add(self, child: Member):
self.children.append(child)
def show(self, level: int):
indent = " " * level
print(indent + self.name)
for child in self.children:
child.show(level + 1)
class Company(Member):
def __init__(self, name: str):
self.root = Department(name)
def add(self, child: Member):
self.root.add(child)
def show(self, level: int):
print("Company Structure:")
self.root.show(level)
def client():
name = input()
company = Company(name)
n = int(input())
for _ in range(n):
memType, memName = input().split()
if memType == "D":
mem = Department(memName)
else:
assert memType == "E"
mem = Employee(memName)
company.add(mem)
company.show(0)
if __name__ == "__main__":
client()