组合模式 Composite
组合模式Composite
组合模式有时候又叫做部分-整体模式,它使我们在树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户与复杂元素的内部结构解耦。
组合模式的意图
将对象组合成树形结构以表示“部分-整体”的层次结构。
Composite模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式(Composite)的组成
1.Component 抽象构件接口
为组合的对象声明接口。
在某些情况下实现从此接口派生出的所有类共有的默认行为。
定义一个接口可以访问及管理它的多个子部件。
2.Leaf 叶部件
在组合中表示叶节点对象,叶节点没有子节点。
定义组合中接口对象的行为。
3.Composite 组合类
定义有子节点(子部件)的部件的行为。
存储子节点(子部件)。
在Component接口中实现与子部件相关的操作。
4.Client 客户端
通过Component接口控制组合部件的对象。
在JUnit中的应用
JUnit中的测试套件Suite是一个复杂元素,但是对于用户来说,TestCase和TestSuite在使用时无需进行区分,这就是应用了组合模式。
组合模式的实现
组合模式有两种实现方式:
1.将管理子元素的方法定义在Composite中。
2.将管理子元素的方法定义在Component接口中。这样Leaf类就要对这些方法空实现。
组合模式的第一种实现
package com.meng.designpattern.composite; //接口:复杂对象和简单对象都实现这个接口,所以外部调用时可相同看待 public interface Component { public void doSomething(); }
叶子节点:
package com.meng.designpattern.composite; public class Leaf implements Component { @Override public void doSomething() { System.out.println("执行方法 -- in Leaf: " + this.toString()); } }
复杂节点:
package com.meng.designpattern.composite; import java.util.List; import java.util.ArrayList; public class Composite implements Component { // List的类型是接口类型Component,这样就既可以放Leaf,又可以放Composite private List<Component> list = new ArrayList<Component>(); public void add(Component component) { list.add(component); } public void remove(Component component) { list.remove(component); } public List<Component> getAll() { return this.list; } @Override public void doSomething() { for (Component component : list) { // 如果是叶子,直接执行 // 如果是复合的,则继续遍历其中包含的list component.doSomething(); } } }
运用:
package com.meng.designpattern.composite; public class Client { public static void main(String[] args) { Component leaf1 = new Leaf(); Component leaf2 = new Leaf(); Composite composite1 = new Composite(); composite1.add(leaf1); composite1.add(leaf2); Component leaf3 = new Leaf(); Component leaf4 = new Leaf(); Composite composite2 = new Composite(); composite2.add(composite1); composite2.add(leaf3); composite2.add(leaf4); // Composite和Leaf执行起来无差别: composite2.doSomething(); leaf4.doSomething(); } }
组合模式的第二种实现
将接口如下定义:
package com.meng.designpattern.composite2; import java.util.List; //这样外部接口可以全是Component public interface Component { public void doSomething(); public void add(Component component); public void remove(Component component); public List<Component> getAll(); }
复合节点的定义如前:
package com.meng.designpattern.composite2; import java.util.ArrayList; import java.util.List; public class Composite implements Component { private List<Component> list = new ArrayList<Component>(); @Override public void doSomething() { for (Component component : list) { component.doSomething(); } } @Override public void add(Component component) { list.add(component); } @Override public void remove(Component component) { list.remove(component); } @Override public List<Component> getAll() { return this.list; } }
但是叶子节点比前面复杂,需要实现接口的全部方法,提供一些空实现:
package com.meng.designpattern.composite2; import java.util.List; public class Leaf implements Component { @Override public void doSomething() { System.out.println("执行方法 -- in Leaf: " + this.toString()); } // 都是空实现 @Override public void add(Component component) { } @Override public void remove(Component component) { } @Override public List<Component> getAll() { return null; } }
客户端调用代码类似,不再重复。这里要注意用第二种实现方法实现时,客户端调用时所有的引用类型都可以用接口类型,因为接口中包含了所有要调用的方法。
参考资料
圣思园张龙老师视频教程。