概念
将对象组合成树形结构以表示“部分-整体”的层次结构。同时可以把一组相似的对象当作一个单一的对象,使得用户对单个对象和组合对象的使用具有一致性。
Component:是组合中的对象声明接口,一般实现所有类(枝节点和叶子)共有接口的默认行为。用于访问和管理Component子部件。
Leaf:在组合中表示叶子结点对象,叶子结点没有子结点。定义叶子行为,无需定义枝节点行为。
Composite:定义了枝节点行为,用来存储子部件。无需定义叶子行为
优点:
- 高层模块调用简单,同单个基础对象的调用方法相同。
- 节点可以自由组合增加。
缺点:
- 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
举例:来自网上
package composite;
public abstract class Component {
//组合对象和基础对象都有的成员和方法
private String name;
public Component() { }
public Component(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//add和remove是组合对象的方法,所以基础对象中不实现进行任何操作。
protected abstract void add(Component company);
protected abstract void romove(Component company);
//display是组合对象的方法,也是基础对象的方法
protected abstract void display(int depth);
}
package composite;
import java.util.ArrayList;
import java.util.List;
public class Composite extends Component {
private List<Component> list;
public Composite() {
list = new ArrayList<>();
}
public Composite(String name) {
super(name);
list = new ArrayList<>();
}
protected void add(Component company) {
list.add(company);
}
protected void display(int depth) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
for (Component c : list) {
c.display(depth + 2);
}
}
//从组合里移除
protected void romove(Component company) {
list.remove(company);
}
}
package composite;
public class LeafOne extends Component{
public LeafOne(String name) {
super(name);
}
protected void add(Component company) { }
protected void display(int depth) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
}
protected void romove(Component company) { }
}
package composite;
public class LeafTwo extends Component {
public LeafTwo(String name) {
super(name);
}
//基础对象根本不用add操作
protected void add(Component company) { }
protected void display(int depth) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
}
//基础对象根本不用romove操作
protected void romove(Component company) { }
}
package composite;
public class Client {
public static void main(String[] args) {
Component root = new Composite();
root.setName("北京总公司");
root.add(new LeafOne("总公司人力资源部"));
root.add(new LeafTwo("总公司财务部"));
Component shandongCom = new Composite("山东分公司");
shandongCom.add(new LeafOne("山东分公司人力资源部"));
shandongCom.add(new LeafTwo("山东分公司账务部"));
Component zaozhuangCom = new Composite("枣庄办事处");
zaozhuangCom.add(new LeafTwo("枣庄办事处财务部"));
zaozhuangCom.add(new LeafOne("枣庄办事处人力资源部"));
Component jinanCom = new Composite("济南办事处");
jinanCom.add(new LeafTwo("济南办事处财务部"));
jinanCom.add(new LeafOne("济南办事处人力资源部"));
shandongCom.add(jinanCom);
shandongCom.add(zaozhuangCom);
Component huadongCom = new Composite("上海华东分公司");
huadongCom.add(new LeafOne("上海华东分公司人力资源部"));
huadongCom.add(new LeafTwo("上海华东分公司账务部"));
Component hangzhouCom = new Composite("杭州办事处");
hangzhouCom.add(new LeafTwo("杭州办事处财务部"));
hangzhouCom.add(new LeafOne("杭州办事处人力资源部"));
Component nanjingCom = new Composite("南京办事处");
nanjingCom.add(new LeafTwo("南京办事处财务部"));
nanjingCom.add(new LeafOne("南京办事处人力资源部"));
huadongCom.add(hangzhouCom);
huadongCom.add(nanjingCom);
root.add(shandongCom);
root.add(huadongCom);
root.display(0);
}
}
//对基础对象的使用和对组合对象的使用并无什么区别