组合模式
解决问题
树结构,多级树形菜单或文件和文件夹目录
方案
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
结构
- 抽象构件角色(component):是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。这个接口可以用来管理所有的子对象。(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
- 树叶构件角色(Leaf):在组合树中表示叶节点对象,叶节点没有子节点。并在组合中定义图元对象的行为。
- 树枝构件角色(Composite):定义有子部件的那些部件的行为。存储子部件。在Component接口中实现与子部件有关的操作。
- 客户角色(Client):通过component接口操纵组合部件的对象。
适用性
- 部分、整体场景,如树形菜单,文件、文件夹的管理。
- 用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
优缺点
- 高层模块调用简单。
- 节点自由增加。
经典实现
目录树结构
// 抽象构件角色
abstract class Node {
abstract public void p();
}
// 树叶构件角色
class LeafNode extends Node {
String content;
public LeafNode(String content) {this.content = content;}
@Override
public void p() {
System.out.println(content);
}
}
// 树枝构件角色
class BranchNode extends Node {
// 树枝中存有抽象构件
List<Node> nodes = new ArrayList<>();
String name;
public BranchNode(String name) {this.name = name;}
@Override
public void p() {
System.out.println(name);
}
public void add(Node n) {
nodes.add(n);
}
}
public class Main {
public static void main(String[] args) {
BranchNode root = new BranchNode("root");
BranchNode chapter1 = new BranchNode("chapter1");
BranchNode chapter2 = new BranchNode("chapter2");
Node r1 = new LeafNode("r1");
Node c11 = new LeafNode("c11");
Node c12 = new LeafNode("c12");
BranchNode b21 = new BranchNode("section21");
Node c211 = new LeafNode("c211");
Node c212 = new LeafNode("c212");
root.add(chapter1);
root.add(chapter2);
root.add(r1);
chapter1.add(c11);
chapter1.add(c12);
chapter2.add(b21);
b21.add(c211);
b21.add(c212);
tree(root, 0);
}
static void tree(Node b, int depth) {
for(int i=0; i<depth; i++) System.out.print("--");
b.p();
if(b instanceof BranchNode) {
for (Node n : ((BranchNode)b).nodes) {
tree(n, depth + 1);
}
}
}
}