介绍
该模式的目的是系统对单个对象和多个对象的使用,具有一致性。比如我们的电脑上,有文件和文件夹(多个对象),新增、删除、修改它们用相同的操作,还有像树形菜单。这样客户端无需辨别到底是单个对象还是多个对象,可以直接操作,给客户带来便利。
角色定义
抽象节点角色:通常是一个抽象类,声明以下2个角色的公共行为操作
树枝节点角色:继承抽象节点角色,实现抽象节点声明的方法。该角色会存储子元素(叶子节点或树枝节点),通常有add()、remove()、getChild()方法来管理子元素
叶子节点角色:继承抽象节点角色,该角色作为存储单元的最下层,没有子元素
模式
组合模式还细分为:透明模式和安全模式。
透明模式:抽象节点角色拥有树枝节点角色和叶子节点角色的所有方法,包含管理子元素的相关方法:add()、remove()、getChild()等(这些方法可以是空处理或者报异常)
安全模式:抽象节点角色只拥有树枝节点角色、叶子节点角色的共有方法,不包含管理子元素的相关方法,只有树枝节点角色有add()、remove()、getChild()等方法
代码示例
透明模式
/**
* 抽象节点角色
*/
public abstract class Root {
protected String name;
public Root(String name) {
this.name = name;
}
public abstract String operation();
public boolean addChild(Root root) {
throw new
UnsupportedOperationException("addChild not supported!");
}
public boolean removeChild(Root root) {
throw new
UnsupportedOperationException("removeChild not supported!");
}
public Root getChild(int index) {
throw new
UnsupportedOperationException("getChild not supported!");
}
}
/**
* 树枝节点角色
*/
public class Branch extends Root {
private List<Root> leafList;
public Branch(String name) {
super(name);
this.leafList = new ArrayList<>();
}
@Override
public String operation() {
StringBuilder builder = new StringBuilder(this.name);
for (Root leaf : this.leafList) {
builder.append(System.getProperty("line.separator"));
builder.append(leaf.operation());
}
return builder.toString();
}
@Override
public boolean addChild(Root root) {
return this.leafList.add(root);
}
@Override
public boolean removeChild(Root root) {
return this.leafList.remove(root);
}
@Override
public Root getChild(int index) {
return this.leafList.get(index);
}
}
/**
* 叶子节点角色
*/
public class Leaf extends Root {
public Leaf(String name) {
super(name);
}
@Override
public String operation() {
return this.name;
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Root root = new Branch("root");
Root branchA = new Branch("--branchA");
Root leafA = new Leaf("--leafA");
Root leafB = new Leaf("----leafB");
Root branchB = new Branch("----branchB");
Root leafC = new Leaf("------leafC");
root.addChild(branchA);
root.addChild(leafA);
branchA.addChild(leafB);
branchA.addChild(branchB);
branchB.addChild(leafC);
String result = root.operation();
System.out.println(result);
}
}
运行结果:
安全模式
/**
* 抽象节点角色
*/
public abstract class Root {
protected String name;
public Root(String name) {
this.name = name;
}
public abstract String operation();
}
// 树枝节点角色那几个方法去除@Override,叶子节点角色代码不动
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Branch root = new Branch("root");
Branch branchA = new Branch("--branchA");
Root leafA = new Leaf("--leafA");
Root leafB = new Leaf("----leafB");
Branch branchB = new Branch("----branchB");
Root leafC = new Leaf("------leafC");
root.addChild(branchA);
root.addChild(leafA);
branchA.addChild(leafB);
branchA.addChild(branchB);
branchB.addChild(leafC);
String result = root.operation();
System.out.println(result);
}
}
运行结果同上,不过客户端要区分树枝节点角色和叶子节点角色,不然无法调用管理子元素的方法。
优缺点
优点:
- 简化了客户端的代码,无需区分是单个对象还是组合对象
- 组合对象自由添加新对象后,对它的操作是不用变动的
缺点:
- 如果组合对象层次多,客户端需要花较多时间理清内部的层次关系