组合模式
组合模式主要描述部分与整体的关系,当我们描述的结构是树形结构时如XML,可以使用组合模式来处理,它最大的好处就是使得用户处理树中根节点、分支节点以及叶子节点具有一致性。
其类图结构如下所示:
抽象构建(Component):定义叶子和容器构建的共同点
叶子(leaf):叶子对象,其下再也没有其他分支
Composite:树枝构件,有容器的特性,组合树枝节点和叶子节点形成一个树形结构
通用代码
抽象构建
抽象构件一般是接口或抽象类,它将个体(叶子)与整体(树枝)的共同方法抽象出来。
public abstract class Component{ public void doSomething(){} }
树枝构件
树枝构件用于添加叶子和子节点
class Composite extends Component { // 构件容器 private ArrayList<Component> components = new ArrayList<Component>(); // 增加一个叶子构件或树枝构件 public void add(Component component){ this.components.add(component); } // 删除一个叶子构件或树枝构件 public void remove(Component component){ this.components.remove(component); } //获取分支下的所有叶子构件和树枝构件 public ArrayList<Component> getChildren(){ return this.components; } }
叶子构件
叶子构件相对比较简单,做一些实事
class Leaf extends Component{ @Override public void doSomething(){ //TODO } }
场景类
class Client{ //创建根节点 static Composite root = new Composite(); public static void main(String[] args) { root.doSomething(); //创建树枝构件 Composite branch = new Composite(); //创建叶子节点 Leaf leaf = new Leaf(); branch.add(leaf); //建立整体 root.add(branch); } public static void display(Composite root){ for (Component c : root.getChildren()) { if(c instanceof Leaf) c.doSomething(); else display((Composite)c); } } }
在使用组合模式时,我们发现在构建整个树的时候,没有什么特点。它的有点主要体现在访问上,因为叶子和树枝都继承自Component,所以高层模块在调用时都进行向上转型,这样不必关心自己处理的是当个叶子还是树枝。
上面的代码并没有完全按照类图来实现,这样使得在添加时使用具体类来操作,遍历时还需要用到强转。不过这样有一个好处就是调用安全。如果我们把在Component中定义了add、remove以及GetChild抽象方法,那么在Leaf中就应该提供相应的处理(抛出非法操作异常)。这种模式称之为透明模式,使得用户调用更加方便。