组合模式(又称“部分-整体”模式)是一种结构型设计模式。组合模式的思想是:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
组合模式涉及3个角色:
- 抽象组件(Component):组合中所有具体组件的抽象接口,用于规范组件的属性和行为,相当于树的节点(Node)。
- 具体组件(Composite):组合中每个具体的组件,相当于树的枝节点。
- 未端具体组件(Leaf):位于未端面的具体组件,没有子节点,相当于树的叶子节点。
结构图:
具体代码实现:
抽象节点:
public abstract class Node {
private String name; // 节点名
public abstract void add(Node node); // 添加一个子节点
public abstract void remove(Node node); // 删除一个子节点
public abstract void eachChild(); // 遍历子节点(包括自身)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
具体节点:
public class Composite extends Node {
private List<Node> list = new ArrayList<>();
public Composite(String name) {
this.setName(name);
}
@Override
public void add(Node node) {
list.add(node);
}
@Override
public void remove(Node node) {
list.remove(node);
}
@Override
public void eachChild() {
System.out.printf("this is %s\n", this.getName()); // 打印自己
for (Node node : list) {
node.eachChild(); // 递归
}
}
}
叶子节点:
public class Leaf extends Node {
public Leaf(String name) {
this.setName(name);
}
@Override
public void add(Node node) {
// 叶子节点不能添加子节点
throw new RuntimeException("Leaf cannot add element!!");
}
@Override
public void remove(Node node) {
// 叶子节点没有子节点可以被删除
throw new RuntimeException("Cannot remove element because Leaf have no Child Node!!");
}
@Override
public void eachChild() {
System.out.printf("this is %s\n", this.getName()); // 打印自己
}
}
树(客户):
public class Tree {
private Node root;
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
public void show() {
root.eachChild();
}
}
// 测试
class CompositeTest {
public static void main(String[] args) {
// 声明若干节点
Node root = new Composite("ROOT");
Node left = new Composite("LEFT");
Node l1 = new Leaf("L1");
Node right = new Composite("RIGHT");
Node r1 = new Leaf("R1");
Node r2 = new Leaf("R2");
// 构造一棵树,遍历看看效果
left.add(l1);
right.add(r1);
right.add(r2);
root.add(left);
root.add(right);
Tree tree = new Tree();
tree.setRoot(root);
tree.show();
// 删除一个节点看看效果
System.out.println("==========");
right.remove(r1);
tree.show();
}
}
运行结果:
this is ROOT
this is LEFT
this is L1
this is RIGHT
this is R1
this is R2
==========
this is ROOT
this is LEFT
this is L1
this is RIGHT
this is R2
组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以向处理简单元素一样来处理复杂元素。
组合模式让你可以优化处理递归或分级数据结构。如果想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。