迭代器模式(Iterator Pattern)
提供一个方法顺序访问一个聚合对象中的元素,而不暴露其内部的表示。
简单点说,Java集合框架中的集合:ArrayList、LinkedList、Vector、Stack、HashMap、HashTable等容器,还有对象数组,要想遍历出里面的所有对象基本每个容器有每个容器的遍历方式,现在我们想不管用什么容器存储这些对象,我都用相同的方式进行遍历。因此,我们需要封装“遍历集合内每个对象的过程”,这个迭代器接口需要有hasNext()方法判断集合内还有没有元素待遍历,有next()方法获取集合内当前遍历到的元素,有remove()方法删除遍历项。而具体的迭代器需要维护该集合以及实现该集合自己的遍历方式。
注意:这里所说的容器、集合、聚合都是一个概念,都是指对象的集合,像ArrayList等。
迭代器模式把元素遍历的责任交给迭代器,而不是聚合对象。让聚合对象的职责更明确更单一,符合单一职责原则。
客户只关心聚合类和迭代器接口,用这个迭代器接口就可以遍历这个聚合(Aggregate)了,不用关心到底用什么具体迭代器实现(每一个具体聚合都要负责实例化一个具体迭代器(所有的具体迭代器都要实现迭代器接口),并返回给客户以便客户遍历自己)。这样,就将客户代码从集合对象的实现解耦了。
- 单一责任原则
- 一个类应该只有一个引起变化的原因
- 类的每个责任都有改变的潜在区域。超过一个责任,意味着超过一个改变的区域。
- Java5以后遍历集合的时候,不需要显示创建迭代器,用for/in语句就行了for (Object obj : collection) { }
组合模式(Composite Pattern)
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
简单点说,就是递归包含,比如说一个菜单,包含多个菜单项,而有的菜单项也可以是一个菜单,这个菜单又包含多个菜单项或子菜单,这种情况下就需要一个接口来一致处理组合(菜单)和个别对象(菜单项)了。
组件有两种:组合和叶节点元素。组合包含组件。组合持有一群孩子,这些孩子可以是组合也可以是叶节点元素。上面的例子中,菜单可以包含其它菜单也可以包含菜单项。
为了能用统一的做法来处理菜单和菜单项,需要创建一个菜单组件接口来作为菜单和菜单项共同的接口。
菜单和菜单项都是组件,而add(Component)、remove(Component)、getChild(int)用来操纵这些组件。
对于菜单的遍历,要用组合迭代器(Composite Iterator),而菜单项的遍历用空迭代器(Null Iterator)。
组合迭代器:
import java.util.Iterator; import java.util.Stack; public class CompositeIterator implements Iterator { Stack stack = new Stack();//存放迭代器的栈 public CompositeIterator(Iterator iterator) { stack.push(iterator);//将顶层组合的迭代器压栈 } public boolean hasNext() { // TODO Auto-generated method stub if (stack.empty()) { return false; } else { Iterator iterator = (Iterator) stack.peek();//查看(peek)栈顶的迭代器 if (!iterator.hasNext()) {//如果没有元素了,弹出栈,递归调用hasNext()看下层还有没有元素 stack.pop(); return hasNext(); } else { return true; } } } public Object next() { // TODO Auto-generated method stub if (hasNext()) { Iterator iterator = (Iterator) stack.peek(); MenuComponent component = (MenuComponent) iterator.next(); if (component instanceof Menu) {//如果元素是个菜单,将它的迭代器压栈 statck.push(component.createIterator()); } return component; } else { return null; } } public void remove() { throw new UnsupportedOperationException(); } }
空迭代器:
import java.util.Iterator; public class NullIterator implements Iterator { // 什么事情都不做,所以永远返回false public boolean hasNext() { // TODO Auto-generated method stub return false; } public Object next() { // TODO Auto-generated method stub return null; } public void remove() { throw new UnsupportedOperationException(); } }
这就像Android里面View和ViewGroup的关系,ViewGroup是一个View子类,而ViewGroup可以包含多个ViewGroup或者View,而对于绘制系统来说我都当作View看待,不管你是ViewGroup还是什么View我都可以遍历、测量、布局、绘制。