一、概述
(1)提供一种方法顺序访问一个聚合对象中的各个元素,而又不要暴露该对象的内部表示。
(2)聚合对象拥有两个职责,一是存储数据,二是遍历数据,而迭代器模式,主要是将数据的遍历功能从聚合对象中分离出来,聚合对象负责存储数据,迭代器负责遍历数据,这样更符合单一职责的原则。
二、结构与实现
- 结构:
结构中包含聚合和迭代器两个层次结构,考虑到灵活性和扩展性,在迭代器模式中应用了工厂方法模式。
(1)Iterator(抽象迭代器):
它定义访问和遍历元素的接口,声明了用于遍历数据元素的方法。比如first()、next()、hasNext()、currentItem()等方法。
(2)ConcreteIterator(具体迭代器):
实现抽象迭代器方法,并维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据。
(3)Aggregate(抽象聚合类):
声明一个createIterator()方法用于创建一个迭代器对象。
(4)ConcreteAggregate(具体聚合类):
实现抽象聚合类中的方法,该方法返回一个与该具体聚合类对应的具体迭代器实例。
- 实现:
//抽象迭代器,也可适用抽象类,并给每一个方法提供一个空的实现。
interface Iterator{
public void first(); //指向第一个元素
public void next(); //指向下一个元素
public boolean hasNext(); //是否存在下一个元素
public Object currentItem(); //获取当前元素
}
//抽象聚合类
interface Aggregate{
public Iterator createIterator();
}
//具体迭代器
class ConcreteAggregate implements Iterator{
private ConcreteAggregate objects;//维持对一个聚合对象的引用
private int cursor;//记录当前访问位置
public ConcreteAggregate(ConcreteAggregate objects){
this.objects=objects;
}
public void first(){...}; //指向第一个元素
public void next(){...}; //指向下一个元素
public boolean hasNext(){...}; //是否存在下一个元素
public Object currentItem(){...}; //获取当前元素
}
//具体聚合类
class ConcreteAggregate implements Aggregate{
...
public Iterator createIterator(){
return new ConcreteIterator(this)
}
...
}
三、应用案例
- 分析:
AbstractObjectList是一个聚合对象,但职责并非单一。此时将引入迭代器,并负责对该聚合对象进行遍历。
ProductList继承抽象聚合类,并实现创建迭代器对象的具体工厂方法。ProductIterator通过构造方法关联ProductList。
- 类图:
- 代码实现:
//抽象聚合对象类
abstract class AbstractObjectList{
protected List<Object> objects=new ArrayList<Object>();
public AbstractObjectList(List<Object> objects){
this.objects=objects;
}
public void addObject(Object obj){
this.objects.add(obj);
}
public void removeObject(Object obj){
this.objects.remove(obj);
}
public List<Object> getObjects(){
return this.objects;
}
public abstract AbstractIterator createIterator();
}
//具体聚合对象类
class ProductList extends AbstractObjectList{
public ProductList(List<Object> objects) {
super(objects);
}
@Override
public AbstractIterator createIterator() {
return new ProductIterator(this);
}
}
//抽象迭代器类
interface AbstractIterator{
public void next();
public boolean isLast();
public void previous();
public boolean isFirst();
public Object getNextItem();
public Object getPreviousItem();
}
//具体迭代器类
class ProductIterator implements AbstractIterator {
private List<Object> products;
private int cursor1;
private int cursor2;
public ProductIterator(ProductList list){
this.products=list.getObjects();
cursor1=0;
cursor2=products.size()-1;
}
@Override
public void next() {
if(cursor1<products.size()){
cursor1++;
}
}
@Override
public boolean isLast() {
return (cursor1==products.size());
}
@Override
public void previous() {
if(cursor2>-1){
cursor2--;
}
}
@Override
public boolean isFirst() {
return (cursor2==-1);
}
@Override
public Object getNextItem() {
return products.get(cursor1);
}
@Override
public Object getPreviousItem() {
return products.get(cursor2);
}
}
public class client {
public static void main(String[] args) {
List<Object> products=new ArrayList<>();
products.add("java");
products.add("php");
products.add("asp");
products.add("python");
AbstractObjectList list;
AbstractIterator iterator;
list=new ProductList(products);//创建聚合对象
iterator=list.createIterator(); //创建迭代器对象
System.out.println("正向遍历");
while (!iterator.isLast()){
System.out.println(iterator.getNextItem()+",");
iterator.next();
}
System.out.println("==============");
System.out.println("逆向遍历");
while (!iterator.isFirst()){
System.out.println(iterator.getPreviousItem()+",");
iterator.previous();
}
}
}
四、扩展
- 内部类实现迭代器(对ProductList类进行修改,将ProductIterator类作为ProductList的内部类)
//具体聚合对象类
public class ProductList extends AbstractObjectList{
public ProductList(List<Object> objects) {
super(objects);
}
@Override
public AbstractIterator createIterator() {
return new ProductIterator(this);
}
//具体迭代器,内部类
private class ProductIterator implements AbstractIterator {
private List<Object> products;
private int cursor1;
private int cursor2;
public ProductIterator(ProductList list){
this.products=list.getObjects();
cursor1=0;
cursor2=products.size()-1;
}
//迭代器里的方法,省略
@Override
public void next() {}
@Override
public boolean isLast() {}
@Override
public void previous() {}
@Override
public boolean isFirst() {}
@Override
public Object getNextItem() {}
@Override
public Object getPreviousItem() {}
}
}
- Java内置迭代器
在Java集合框架中,常用的List和Set等聚合类都继承(或实现)了Collection。
public class demo{
public static void process(Collection c){
Iterator i=c.iterator();
while(i.hasNext()){
System.out.println(i.next().toString());
}
}
public static void main(String args[]){
Collection persons;
persons=new ArrayList();
persons.add("jack");
persons.add("har");
process(persons)
}
}
五、总结
- 聚合对象既可以存储数据又可以遍历数据,这将违背单一职责的原则,而迭代器模式就是将聚合对象进行分离,引入迭代器进行遍历数据,之后聚合对象就只负责存储数据,这样更符合单一职责的原则。
- 迭代器模式中的具体迭代器类对聚合对象进行关联,并提供遍历方法,具体聚合对象提供迭代器的创建方法。