组合(composite)模式

来源:互联网 发布:windows应用程序编程 编辑:程序博客网 时间:2024/05/22 01:46

组合模式:允许你将对象组合成树型结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

一、组合模式

 要点:

1. 组合模式以不遵守单一责任原则换取透明性,让Client将组合和叶节点一视同仁。

2. 在实现组合模式时,有很多设计上的折衷。要根据需求平衡透明性和安全性。

3. 有时候系统需要遍历一个树枝构件的子构件很多次,这时候可以把遍历结果缓存起来。

4. 组合模式的实现中,可以让子对象持有父对象的引用进行反向追溯。 

实现:

clip_image002

Component:为参加组合的对象声明一个公共接口,不管是组合还是叶节点。

public abstract class Component {public void add(Component component) {throw new UnsupportedOperationException();}public void remove(Component component) {throw new UnsupportedOperationException();}public Component getChild(int i) {throw new UnsupportedOperationException();}public void operation() {throw new UnsupportedOperationException();}}

Leaf:在组合中表示叶节点对象,叶节点没有子节点。

public class Leaf extends Component{@Overridepublic void operation(){//your code}}

 Composite:表示参加组合的有子对象的对象,并给出树枝构件的行为。 

public class Composite extends Component{ArrayList<Component> components = new ArrayList<Component>();@Overridepublic void add(Component component){components.add(component);}@Overridepublic void remove(Component component){components.remove(component);}@Overridepublic Component getChild(int i){return components.get(i);}@Overridepublic void operation(){for (Component component : components){component.operation();}}}

适用性:

以下情况使用Composite模式:

1. 你想表示对象的部分-整体层次结构。

2. 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。 

优点:

1. 组合模式可以很容易的增加新的构件。

2. 使用组合模式可以使客户端变的很容易设计,因为客户端可以对组合和叶节点一视同仁。

缺点:

1. 使用组合模式后,控制树枝构件的类型不太容易。

2. 用继承的方法来增加新的行为很困难。

二、Junit中使用的组合模式

Junit中有连个重要的概念,一个是TestCase一个是TestSuiteTestSuite是一个测试集合,一个TestSuite中可以包含一个或者多个TestSuite,当然也可以一个或者多个TestCase,而这两个对象都继承与Test接口。这样一分析,Test接口相当于组合模式中的抽象构件角色(Component),TestSuite相当于树枝构件角色(Composite),TestCase相当于树叶构件角色(Leaf)。接着我们对具体代码分析看看这块是否满足组合模式。

Test接口类:public interface Test {     public abstract int countTestCases();     public abstract void run(TestResult result);}TestSuite实现:   public int countTestCases() {     int count= 0;     for (Enumeration e= tests(); e.hasMoreElements(); ) {        Test test= (Test)e.nextElement();        count= count + test.countTestCases();     }     return count;  }   public void run(TestResult result) {     for (Enumeration e= tests(); e.hasMoreElements(); ) {        if (result.shouldStop() )            break;        Test test= (Test)e.nextElement();        runTest(test, result);     }}TestCase实现   public int countTestCases() {     return 1;  }  public void run(TestResult result) {     result.run(this);}

根据代码分析,Junit使用Composite模式后简化了JUnit的代码,JUnit可以统一处理组合结构TestSuite和单个对象TestCase。使JUnit开发变得简单容易,因为不需要区分部分和整体的区别,不需要写一些充斥着if else的选择语句。

另外,通过对TestCase对象和TestSuite的类层次结构基本对象的定义,TestCase可以被组合成更复杂的组合对象TestSuite,而这些组合对象又可以被组合,这样不断地递归下去。在程序的代码中,任何使用基本对象的地方都可方便的使用组合对象,大大简化系统维护和开发。

三、head first dp中的迭代器&组合

public class CompositeIterator implements Iterator {     Stack stack = new Stack();//堆栈内每个元素都是一个迭代器     public CompositeIterator(Iterator iterator) {         stack.push(iterator);     }     public Object next() {         if (hasNext()) {             Iterator iterator = (Iterator) stack.peek();//查看栈顶元素,并没有弹出栈             MenuComponent component = (MenuComponent) iterator.next();//取出栈顶元素下一个元素             if (component instanceof Menu) {                 stack.push(component.createIterator());             }             return component;         } else {             return null;         }     }     public boolean hasNext() {         if (stack.empty()) {             return false;         } else {             Iterator iterator = (Iterator) stack.peek();             if (!iterator.hasNext()) {                 stack.pop();//此时的栈顶元素下面已经没有子节点或者子节点已经被遍历过了,就删除这个子节点                 return hasNext();//然后递归插线下个栈顶元素             } else {                 return true;             }         }     }     public void remove() {         throw new UnsupportedOperationException();     } }
ref:http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755844.html
      http://blog.sina.com.cn/s/blog_6e0d94750101653y.html