组合模式
结构型模式
访问次数: 12
组合模式将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
视频教程
类图
classDiagram
class Component {
<<interface>>
+operation()
+add(component: Component)
+remove(component: Component)
+getChild(index: int) Component
}
class Leaf {
+operation()
}
class Composite {
-children: List~Component~
+operation()
+add(component: Component)
+remove(component: Component)
+getChild(index: int) Component
}
Component <|-- Leaf
Component <|-- Composite
Composite --> Component : contains
源代码示例
// 抽象组件
interface Component {
void operation();
void add(Component component);
void remove(Component component);
Component getChild(int index);
}
// 叶子节点
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Leaf " + name + " operation");
}
@Override
public void add(Component component) {
throw new UnsupportedOperationException("Cannot add to leaf");
}
@Override
public void remove(Component component) {
throw new UnsupportedOperationException("Cannot remove from leaf");
}
@Override
public Component getChild(int index) {
throw new UnsupportedOperationException("Leaf has no children");
}
}
// 组合节点
class Composite implements Component {
private String name;
private List<Component> children = new ArrayList<>();
public Composite(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Composite " + name + " operation");
for (Component child : children) {
child.operation();
}
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public Component getChild(int index) {
return children.get(index);
}
}
# Python代码待添加
应用场景
当需要表示树形结构,且希望对叶子节点和组合节点进行统一处理时。应用场景包括:
1)文件系统中的文件和文件夹,可以对文件和文件夹执行统一的操作(复制、删除、移动)
2)图形界面中的容器和控件,容器可以包含其他容器或控件,形成嵌套的UI结构
3)组织结构管理,公司、部门、员工形成树形结构,可以统一处理组织关系
4)菜单系统,菜单项可以是叶子节点(具体功能)或组合节点(子菜单)
5)XML/HTML文档结构,元素可以包含文本节点或其他元素节点
6)游戏场景图,场景可以包含子场景、游戏对象、特效等不同类型的节点
精选场景详解 —— 文件系统:统一处理文件与文件夹
问题背景
复制/删除/统计大小时,若对 File 和 Folder 写两套逻辑,客户端要不断判断类型;文件夹又可嵌套文件夹,结构是递归树。
模式如何解决
选用组合模式:FileSystemNode 作为统一组件接口;File 是叶子,Folder 是容器并持有子节点列表。客户端对根节点调用 display/delete/getSize,无需区分叶子与容器。
结构上形成树:Folder → (File | Folder)*。
适用特征:部分-整体层次、希望「透明地」对单个对象与组合对象使用同一操作。UI 控件树、组织架构、菜单树同理。
场景模型(角色映射)
将模式中的抽象角色映射到该业务领域的具体类:
classDiagram
class FileSystemNode {
<<interface>>
+getName() String
+getSize() long
+display(indent: int)
+delete()
}
class FileNode {
-size: long
+getSize() long
+display(indent: int)
+delete()
}
class FolderNode {
-children: List~FileSystemNode~
+add(node: FileSystemNode)
+remove(node: FileSystemNode)
+getSize() long
+display(indent: int)
+delete()
}
class FileManager {
+copy(src: FileSystemNode, dest: FolderNode)
}
FileSystemNode <|.. FileNode
FileSystemNode <|.. FolderNode
FolderNode --> FileSystemNode : contains
FileManager --> FileSystemNode