定义:将对象组合成树形结构以表示 “部分 — 整体” 的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。
类型:对象结构型模式
类图:
组合模式的结构
组合模式(Composite)有两种实现方式:透明方式和安全方式
透明方式:在Component中声明所有用来管理子对象的方法,如Add()方法,Remove()方法及GetChild()方法,所有实现Component接口的子类都具备这些方法,这使得Component和子类具备一致的行为接口,使得对客户端无需区别树叶和树枝对象。
大家可以回忆一下代理模式(Proxy)中,Proxy,RealSubject类和Subject接口具备一致的行为接口,从而使得被代理者对于客户端是透明的。
正由于我们的Composite和Leaf都具备一致的接口行为,但我们知道Leaf不应该具有Add(),Remove()及GetChild()方法,因为我们叶子节点不能再添加和移除节点了。
安全模式:在透明模式基础上把Component中声明所有用来管理子对象的方法移到Composite中,在Composite实现子对象的管理方法,那么Leaf就没有子对象管理方法,这使得Composite和Leaf的行为接口不一致,所以客户端在调用时要知道树叶和树枝对象存在。
Composite模式透明方式实现代码
首先我们定义一个抽象类Componet,在其中声明add(),remove()等子对象操作
// 抽象类接口 Component abstract class Component { public abstract int getChildNum(); public abstract String getName(); public abstract String getType(); public abstract void add(Component c); public abstract void remove(Component c); }
接着我们定义Composite类继承于Component,增加childList保存Component对象的引用,从而建立起由Component到Composite的聚集关系(Has-a关系),并且实现Component抽象类中的抽象方法。
// 树枝节点 Composite类继承于Component class Composite extends Component { private String nodeName; private List<Component> childList; //保存孩子节点 public Composite(String nodeName) { this.nodeName = nodeName; childList = new ArrayList<Component>(); } @Override public int getChildNum() { return childList.size(); } @Override public String getName() { return this.nodeName; } @Override public String getType() { return "Composite"; } @Override public void add(Component c) { childList.add(c); } @Override public void remove(Component c) { childList.remove(c); } }
// 叶子节点 Leaf类 也继承于Component class Leaf extends Component { private String nodeName; public Leaf(String nodeName) { this.nodeName = nodeName; } @Override public int getChildNum() { return 0; } @Override public String getName() { return this.nodeName; } @Override public String getType() { return "Leaf"; } @Override public void add(Component c) { System.err.println("ERROR ! Leaf Not supported add method!"); } @Override public void remove(Component c) { System.err.println("ERROR ! Leaf Not supported remove method!"); } }
//客户 Client public class CompositeClient { /** * @param args */ public static void main(String[] args) { Component root = new Composite("root"); //根节点 Component composite = new Composite("composite"); //树枝节点 //叶节点 Component leaf1 = new Leaf("leaf1"); Component leaf2 = new Leaf("leaf2"); composite.add(leaf2); root.add(leaf1); root.add(composite); String str = "Leaf1's size is " + leaf1.getChildNum(); str += "\nleaf2's size is " + leaf2.getChildNum(); str += "\nComposite's size is " + composite.getChildNum(); str += "\nRoot's size is " + root.getChildNum(); System.out.println(str); } }
Composite适用场景
Composite组合模式的几个要点:
总结