首页 > 代码库 > JAVA设计模式之 迭代器模式【Iterator Pattern】

JAVA设计模式之 迭代器模式【Iterator Pattern】

一、概述

    提供一种方法来访问聚合对象(容器container),而不用暴露这个对象的内部细节。

二、适用场景

    1>遍历访问聚合对象中的元素,而无须暴露它的内容表示,将聚合对象的访问和内部数据的存储分离。使得访问聚合对象时无须了解其内部的实现细节。

    2>需要为一个聚合对象提供多种遍历实现。


三、UML类图


四、参与者

 1>Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法,例如:用于获取第一个元素的first()方法,用于访问下一个元素的next()方法,用于判断是否还有下一个元素的hasNext()方法,用于获取当前元素的currentItem()方法等,在具体迭代器中将实现这些方法。

 2>ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。

 3>Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。

 4>ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。


五、用例学习

1、抽象迭代器 Iterator.java

/**
 * 自定义迭代器接口<br/>
 * <b>说明:</b>
 * 此处没有使用JDK内置的迭代器接口 java.util.Iterator<E>
 * @author  lvzb.software@qq.com
 *
 */
public interface Iterator {
    /** 将游标指向第一个元素  */
	public Object first();
	/** 将游标指向下一个元素  */
	public Object next();
	/** 判断是否存在下一个元素  */
	public boolean hasNext();
	/** 返回游标指向的当前元素  */
	public Object currentItem();
}

2、具体迭代器 ConcreteIterator.java

/**
 * 具体迭代器实现类<br/>
 * 访问聚合对象、对聚合对象内部元素遍历
 * @author  lvzb.software@qq.com
 *
 */
public class ConcreteIterator implements Iterator {
	// 维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据  
	private Aggregate aggregate;
	// 定义一个游标,用于记录当前访问位置  
	private int cursorIndex; 

	public ConcreteIterator(Aggregate aggregate){
		this.aggregate = aggregate;
	}
	
	@Override
	public Object first() {
		cursorIndex = 0;
        return aggregate.getObjects().get(cursorIndex);
	}

	@Override
	public Object next() {
		cursorIndex++ ;
		if(hasNext()){
			return aggregate.getObjects().get(cursorIndex);
		} 
		return aggregate.getObjects().get(0);
	}

	@Override
	public boolean hasNext() {
		if (cursorIndex < aggregate.getObjects().size()) {
			return true;
		}
		return false;
	}

	@Override
	public Object currentItem() {
		return aggregate.getObjects().get(cursorIndex);
	}

}
3、抽象聚合类 Aggregate.java

import java.util.ArrayList;
import java.util.List;

/**
 * 抽象聚合对象
 * @author  lvzb.software@qq.com
 *
 */
public abstract class Aggregate {
	
	/** 创建迭代器  具体创建什么样迭代方式的迭代器由具体的子类去实现 */
	public abstract Iterator createIterator();
	
    protected List<Object> objects = new ArrayList<Object>();  
	
	public Aggregate(List objects) {  
        this.objects = objects;  
    } 
	
	public void addObject(Object obj){
		objects.add(obj);
	}
	
	public void deleteObject(Object obj){
		objects.remove(obj);
	}
	
	public List<Object> getObjects(){
		return objects;
	}

}
4、具体聚合类 ConcreteAggregate.java

import java.util.List;

/**
 * 具体聚合对象
 * @author  lvzb.software@qq.com
 *
 */
public class ConcreteAggregate extends Aggregate {

	public ConcreteAggregate(List objects) {
		super(objects);
	}

	/**
	 * 提供工厂方法 创建具体的迭代器实例<br/>
	 * 由迭代器去执行具体的聚合对象的遍历访问<br/>
	 * 这样就将聚合对象的数据存储 和 对聚合对象元素的访问进行了分离
	 */
	@Override
	public Iterator createIterator() {
		return new ConcreteIterator(this);
	}

}
5、客户端测试类 Client.java

import java.util.ArrayList;
import java.util.List;

public class Client {

	public static void main(String[] args){
		List<String> nameList = new ArrayList<String>();
		nameList.add("Java");
		nameList.add("C");
		nameList.add("C++");
		
		// 实例化具体聚合对象 且 创建初始化集合数据
		ConcreteAggregate languageAggregate = new ConcreteAggregate(nameList);
		// 获取聚合对象关联的迭代器
		Iterator iterator = languageAggregate.createIterator();
		
		// 通过迭代器访问聚合对象的内部数据
		String firstLanguage = (String) iterator.first();  // 访问聚合对象集合中索引为1的元素 
		System.out.println(firstLanguage);
		
		boolean hasNext = iterator.hasNext();
		System.out.println("是否还有下一个元素:" + hasNext);
		
		if(hasNext){
			String nextLanguage = (String) iterator.next(); 
			System.out.println("下一个元素:" + nextLanguage);
		}
	}
	
}
6、运行效果

Java
是否还有下一个元素:true
下一个元素:C



六、其他/扩展

Java JDK内置的迭代器:

    说到迭代器模式 给我们的第一联想就是Java中 我们使用最最频繁的java.util.Iterator接口啦。

没错 他就是JDK中内置的迭代器。public interfaceIterator<E> 对collection进行迭代的迭代器。

 

    这里想扩展的一个点是:关于接口Iterator的子接口ListIterator<E>的介绍

这个ListIterator子接口 也许我们平时的代码中使用的少,那么他有什么功能呢?

下面先看两张截图<比较比较 答案就在其中>

Iterator API方法:


ListIterator API方法:


从上面两个截图分析中我们可以看出Iterator只能进行单向遍历,而ListIterator可以进行双向遍历(向前/向后),且可以在迭代期间修改列表。最后附上一张截图如下:






JAVA设计模式之 迭代器模式【Iterator Pattern】