组合模式:
组合模式(Composite Pattern)属于结构型的设计模式,它允许你将对象组合成树形结构,并且以统一的方式处理单个对象与对象组合。在组合模式中,单个对象与复合对象都可以通过相同接口进行访问和操作,从而实现对整个对象树的透明化处理。
角色和结构:
1 Component(组件):
- 这是所有对象(包括叶子节点和容器节点)的基类或接口。
- 定义了所有对象共有的方法,如添加、删除子节点以及获取子节点的方法。
- 可以包含一部分默认行为,对于复杂操作可能由具体组件来完成。
2 Leaf(叶子节点):
- 实现容器接口的最简单形式,代表树中的叶子对象。
- 叶子节点通常提供具体的业务逻辑实现。
3 Composite(容器节点/组合体):
- 同样实现容器接口,但它的内部可以包含其他容器对象,即它可以包含子节点。
- 提供管理其子节点的方法,例如添加、删除子节点等。
- 递归地对其子节点调用相应的方法,使得客户端代码可以一致地处理单个组件和整个组件树。
工作原理:
- 当客户端调用容器接口的方法时,如果是针对叶子节点,那么直接执行相应的行为;如果针对的是容器节点,则会遍历其内部的所有子节点并递归调用这些方法。
- 由于叶子节点和容器节点都实现了相同的接口,因此它们可以互换使用,客户端无需了解处理的是单个对象还是对象集合。
示例代码:
组合模式示例代码:
// Component 接口或抽象类
public abstract class Component {
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract void operation();
}
// Leaf 类
public class Leaf extends Component {
@Override
public void add(Component component) {
// 不支持添加子节点的操作
throw new UnsupportedOperationException();
}
@Override
public void remove(Component component) {
// 不支持移除子节点的操作
throw new UnsupportedOperationException();
}
@Override
public void operation() {
// 叶子节点的具体业务逻辑实现
System.out.println("Leaf operation");
}
}
// Composite 类
public class Composite extends Component {
private List<Component> children = new ArrayList<>();
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
// 执行自身的操作
System.out.println("Composite operation");
// 遍历并执行子节点的操作
for (Component child : children) {
child.operation();
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
Component composite = new Composite();
composite.add(leaf1);
composite.add(leaf2);
composite.operation(); // 输出 "Composite operation" 和两次 "Leaf operation"
}
}
说明:在上面代码中Component
是通用接口,Leaf
是叶子节点,而 Composite
是组合节点。当调用 composite.operation()
时,它会先执行自身的方法,再递归调用每个子节点的 operation()
方法。
组合模式的优点:
- 统一处理方式:无论对象是简单的还是复杂的,客户端都可以使用统一的方式来处理。
- 简化客户端代码:客户端无需关注处理的对象是否为单一对象还是组合对象。
- 可灵活扩展:当需要增加新的组件类型时,只需创建一个新的 Component 类即可,不需要修改现有客户端代码。
组合模式的应用场景:
- 文件系统中的目录与文件结构,其中目录可以包含子目录和文件,而文件不能包含其他内容。
- HTML DOM 树,元素既可以是简单的文本节点也可以是包含其他元素的容器节点。
- UI 框架中的组件组织,如菜单项可以是一个单独的按钮或一个包含多个子菜单项的容器。