组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
实现代码如下:
1 /** 2 * Component为组合中的对象声明接口,在适当情况下,实现所有类共有的接口的默认行为 3 */ 4 abstract class Component { 5 String name; 6 public Component(String name){ 7 this.name=name; 8 } 9 public abstract void add(Component c); 10 public abstract void remove(Component c); 11 public abstract void foreach(); 12 }
1 /** 2 * 组合类 定义有枝节点行为,用来存储子部件,实现Component中与子部件有关的操作 3 */ 4 public class Composite extends Component { 5 // 用来保存节点的子节点 6 private List<Component> child=new ArrayList<>(); 7 8 public Composite(String name) { 9 super(name); 10 } 11 // 添加节点 添加部件 12 @Override 13 public void add(Component c) { 14 child.add(c); 15 } 16 // 删除节点 删除部件 17 @Override 18 public void remove(Component c) { 19 child.remove(c); 20 } 21 // 遍历子节点 22 @Override 23 public void foreach() { 24 System.out.println("节点名: "+name); 25 for (Component c:child 26 ) { 27 c.foreach(); 28 } 29 } 30 }
1 /** 2 * 组合部件类 叶节点对象,没有子节点 3 */ 4 public class Leaf extends Component { 5 6 public Leaf(String name) { 7 super(name); 8 } 9 10 // 叶子节点不具备添加的能力,所以不实现 11 @Override 12 public void add(Component c) { 13 14 } 15 // 叶子节点不具备添加的能力必然也不能删除 16 @Override 17 public void remove(Component c) { 18 19 } 20 // 叶子节点没有子节点所以显示自己的执行结果 21 @Override 22 public void foreach() { 23 System.out.println("tself name-->"+this.name); 24 } 25 }
客户端
public class Client { public static void main(String[] args) { // 构造根节点 Component component=new Composite("根结点"); Component child=new Composite("一级子节点child"); Component child_1=new Leaf("一级子节点child之子节点一"); Component child_2=new Leaf("一级子节眯child之子节点二"); child.add(child_1); child.add(child_2); Component child2=new Composite("一级子节点child2"); component.add(child); component.add(child2); component.foreach(); } }
透明方式与安全方式
“树可能有无数的分枝,但只需要反复用Composite就可以实现树状结构了。“
”为什么Leaf类当中也有Add和Remove,树叶不是不可以再长分枝吗?“
”是的,这种方式叫做透明模式,也就是说Component中声明的所有用来管理子对象的方法,其中包括Add,Remove等。这样实现Component接口所有子类都具备了Add和Remove。这样
做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它没有意义。“
”那么如果我不希望做这样的无用功呢?也就是Leaf类当中不用Add和Remove方法,可以吗?“
”当然可以,那么就需要安全方式,也就是在Component接口中不去声明 Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Component声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝将不具有相同的接口,客户端的调用需要做出相应的判断,带来了不便。“
”那我喜欢透明模式,那样就不用做任何判断了。" --摘自《大话设计模式》
何时使用组合模式
当你发现需求中是体现部分与整体层次的结构是地,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。
组合模式的好处
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。这样用户是不用关系到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。组合模式让客户可以一致地使用组合结构和单个对象。