在迭代器模式的实现中,常见有两个地方可以来定义遍历算法,一个就是聚合对象本身,另外一个就是迭代器负责遍历算法。
在聚合对象本身定义遍历的算法这种情况下,通常会在遍历过程中,用迭代器来存储当前迭代的状态,这种迭代器被称为游标,因为它仅用来指示当前的位置。
在迭代器里面定义遍历算法,会易于在相同的聚合上使用不同的迭代算法,同时也易于在不同的聚合上重用相同的算法。比如上面带策略的迭代器的示例,迭代器把需要迭代的数据从聚合对象中取出并存放到自己对象里面,然后再迭代自己的数据,这样一来,除了刚开始创建迭代器的时候需要访问聚合对象外,真正迭代过程已经跟聚合对象无关了。
双向迭代器
所谓双向迭代器的意思就是:可以同时向前和向后遍历数据的迭代器。
在Java util包中的ListIterator接口就是一个双向迭代器的示例,当然自己实现双向迭代器也非常容易,只要在自己的Iterator接口中添加向前的判断和向前获取值的方法,然后在实现中实现即可。
/**
* 迭代器接口,定义访问和遍历元素的操作,实现双向迭代
*/
public interface Iterator {
/**
* 移动到聚合对象的第一个位置
*/
public void first();
/**
* 移动到聚合对象的下一个位置
*/
public void next();
/**
* 判断是否已经移动聚合对象的最后一个位置
* @return true表示已经移动聚合对象的最后一个位置,
*
false表示还没有移动到聚合对象的最后一个位置
*/
public boolean isDone();
/**
* 获取迭代的当前元素
* @return 迭代的当前元素
*/
public Object currentItem();
/**
* 判断是否为第一个元素
* @return 如果为第一个元素,返回true,否则返回false
*/
public boolean isFirst();
/**
* 移动到聚合对象的上一个位置
*/
public void previous();
}
----------
/**
* 用来实现访问数组的双向迭代接口
*/
public class ArrayIteratorImpl implements Iterator{
/**
* 用来存放被迭代的聚合对象
*/
private SalaryManager aggregate = null;
/**
* 用来记录当前迭代到的位置索引
* -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
*/
private int index = -1;
public ArrayIteratorImpl(SalaryManager aggregate){
this.aggregate = aggregate;
}
public void first(){
index = 0;
}
public void next(){
if(index < this.aggregate.size()){
index = index + 1;
}
}
public boolean isDone(){
if(index == this.aggregate.size()){
return true;
}
return false;
}
public Object currentItem(){
return this.aggregate.get(index);
}
public boolean isFirst(){
if(index==0){
return true;
}
return false;
}
public void previous(){
if(index > 0 ){
index = index - 1;
}
}
}
----------
/**
* 收购的那个公司的工资管理类
*/
public class SalaryManager{
/**
* 用数组管理
*/
private PayModel[] pms = null;
/**
* 获取工资列表
* @return 工资列表
*/
public PayModel[] getPays(){
return pms;
}
/**
* 计算工资,其实应该有很多参数,为了演示从简
*/
public void calcSalary(){
//计算工资,并把工资信息填充到工资列表里面
//为了测试,做点假数据进去
PayModel pm1 = new PayModel();
pm1.setPay(2200);
pm1.setUserName("王五");
PayModel pm2 = new PayModel();
pm2.setPay(3600);
pm2.setUserName("赵六");
pms = new PayModel[2];
pms[0] = pm1;
pms[1] = pm2;
}
public Iterator createIterator(){
return new ArrayIteratorImpl(this);
}
public Object get(int index){
Object retObj = null;
if(index < pms.length){
retObj = pms[index];
}
return retObj;
}
public int size(){
return this.pms.length;
}
}
----------
public class Client {
public static void main(String[] args) {
//访问新收购公司的工资列表
SalaryManager salaryManager = new SalaryManager();
//先计算再获取
salaryManager.calcSalary();
//得到双向迭代器
Iterator it = salaryManager.createIterator();
//首先设置迭代器到第一个元素
it.first();
//先next一个
if(!it.isDone()){
PayModel pm = (PayModel)it.currentItem();
System.out.println("next1 == "+pm);
//向下迭代一个
it.next();
}
//然后previous一个
if(!it.isFirst()){
//向前迭代一个
it.previous();
PayModel pm = (PayModel)it.currentItem();
System.out.println("previous1 == "+pm);
}
//再next一个
if(!it.isDone()){
PayModel pm = (PayModel)it.currentItem();
System.out.println("next2 == "+pm);
//向下迭代一个
it.next();
}
//继续next一个
if(!it.isDone()){
PayModel pm = (PayModel)it.currentItem();
System.out.println("next3 == "+pm);
//向下迭代一个
it.next();
}
//然后previous一个
if(!it.isFirst()){
//向前迭代一个
it.previous();
PayModel pm = (PayModel)it.currentItem();
System.out.println("previous2 == "+pm);
}
}
}
迭代器模式的优缺点