被说了很多遍的设计模式---迭代器模式

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍迭代器模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk8

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

某一个特定集合(聚合)的遍历(迭代)

思路分析:

要点一:所谓遍历,就是要无一例外的全部访问。

要点二:遍历(迭代)只讲全面,而忽略顺序。即,任何位置的元素都可以作为起点。

示例工程:


迭代器模式模板代码:


创建Aggregate.java文件,具体内容如下:

package com.csdn.ingo.gof_Iterator;

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

public abstract class Aggregate {
	protected List<Object> objects = new ArrayList<Object>();
	public Aggregate(List objects){
		this.objects = objects;
	}
	public void add(Object obj){
		this.objects.add(obj);
	}
	public void remove(Object obj){
		this.objects.remove(obj);
	}
	public List getObjects(){
		return this.objects;
	}
	
	public abstract Iterator createIterator();
}
创建ConcreteAggregate.java文件,具体内容如下:

package com.csdn.ingo.gof_Iterator;

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

public class ConcreteAggregate extends Aggregate {
	public ConcreteAggregate(List objects) {
		super(objects);
		// TODO Auto-generated constructor stub
	}
	private List<Object> items = new ArrayList<Object>();
	public int Count;
	@Override
	public Iterator createIterator() {
		return new ConcreteIterator(this);
	}
	public int getCount() {
		return items.size();
	}
	public void setCount(int count) {
		Count = count;
	}
}
创建ConcreteIterator.java文件,具体内容如下:

package com.csdn.ingo.gof_Iterator;

import java.util.List;

public class ConcreteIterator extends Iterator {
	private ConcreteAggregate aggregate;
	private List aggregates;
	private int cursor1;
	private int cursor2;
			
	public ConcreteIterator (ConcreteAggregate aggregate){
		this.aggregate = aggregate;
		this.aggregates = aggregate.getObjects();
		cursor1 = 0;
		cursor2 = aggregates.size()-1;
	}

	@Override
	public boolean isFirst() {
		return (cursor2==-1);
	}
	@Override
	public void previous() {
		if(cursor2>-1){
			cursor2--;
		}
	}
	@Override
	public boolean isLast() {
		return (cursor1==aggregates.size());
	}
	@Override
	public Object getCurrentItem() {
		return aggregates.get(cursor1);
	}
	@Override
	public Object getPreviousItem() {
		return aggregates.get(cursor2);
	}

	@Override
	public void next() {
		if(cursor1<aggregates.size()){
			cursor1++;
		}
	}
}
创建Iterator.java文件,具体内容如下:

package com.csdn.ingo.gof_Iterator;

public abstract class Iterator 
{
    public abstract boolean isFirst();
    public abstract void next();
    public abstract void previous();
    public abstract boolean isLast();
    public abstract Object getCurrentItem();
    public abstract Object getPreviousItem();
}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Iterator;

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

public class Window {
	public static void main(String[] args) {
		List products =new ArrayList();
		products.add("AAA");
		products.add("BBB");
		products.add("CCC");
		products.add("DDD");
		products.add("EEE");
		
		Iterator iterator;
		Aggregate list;
		list = new ConcreteAggregate(products);
		iterator = list.createIterator();
		
		System.out.println("---正向遍历---");
		while(!iterator.isLast()){
			System.out.println(iterator.getCurrentItem()+",");
			iterator.next();
		}
		System.out.println("------------");
		System.out.println("---反向遍历---");
		while(!iterator.isFirst()){
			System.out.println(iterator.getPreviousItem()+",");
			iterator.previous();
		}
	}
}
【上面的代码直接看的话,可能有难度。先把代码提供给各位看官是希望现将代码运行起来,观察结果。下面我们介绍相关的概念与原理】

模式总结:

迭代器模式结构图:


迭代器模式:

提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示

组成部分:

Iterator(抽象迭代器):定义了访问和遍历元素的接口,声明了用于遍历元素的方法。

ConcreteIterator(具体迭代器):实现抽象迭代器,完成对聚合对象的遍历,并且通过游标记录当前遍历的索引位置。

Aggregate(抽象聚合类):用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象。

ConcreteAggregate(具体聚合类):实现了抽象聚合类,返回一个具体的迭代器实例。

特别提醒:迭代器模式应用到了工厂方法模式的设计方法。【详情参考:http://blog.csdn.net/abcd898989/article/details/52859560

JDK的内置迭代器:【以下内容来自其他博文与JDK源码】

在java中,常见的list与set都继承或者实现了java.util.Collection接口。

Collection的具体内容如下:


我们看到除了add,remove方法外,还提供了iterator方法,用于返回一个迭代器对象。具体的java聚合类可以通过实现该iterator方法返回一个具体的迭代器对象。

JDK中定义的抽象迭代器接口内容如下:


以上方法的官方解释如下:



测试代码:

package com.csdn.ingo.gof_Iterator;

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

public class Window {
	public static void main(String[] args) {
		List products =new ArrayList();
		products.add("AAA");
		products.add("BBB");
		products.add("CCC");
		products.add("DDD");
		products.add("EEE");
		java.util.Iterator iterator = products.iterator();
		iterator.next();
		iterator.remove();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
}
特别提醒:remove()方法本身没有移动游标的位置。因此,在当前位置调用了remove()方法后,当前位置等于是“空”元素。如果不移动游标位置,再次调用remove()方法,将会抛出如下异常:


JDK的List与迭代器的实现说明,如下图:【以下内容自于其他博文,详情参考文章末尾】


 在JDK中,实际情况比上图要复杂很多,在中,List接口除了继承Collection接口的iterator()方法外,还增加了新的工厂方法listIterator(),专门用于创建ListIterator类型的迭代器。


List的子类LinkedList中实现了该方法,可用于创建具体的ListIterator子类ListItr的对象,如下所示:


  listIterator()方法用于返回具体迭代器ListItr类型的对象。在JDK源码中,AbstractList中的iterator()方法调用了listIterator()方法,如下:


客户端通过调用LinkedList类的iterator()方法,即可得到一个专门用于遍历Linkedlist的迭代器对象。

问题:

       既然有了iterator()方法,为什么还要提供一个listIterator()方法呢?这两个方法的功能不会存在重复吗?

解释:

       由于在Iterator接口中定义的方法太少,只有三个,通过这三个方法只能实现正向遍历,而有时候我们需要对一个聚合对象进行逆向遍历等操作,因此在JDKListIterator接口中声明了用于逆向遍历的hasPrevious()previous()等方法,如果客户端需要调用这两个方法来实现逆向遍历,就不能再使用iterator()方法来创建迭代器了,因为此时创建的迭代器对象是不具有这两个方法的。我们只能通过如下代码来创建ListIterator类型的迭代器对象:ListIterator i = c.listIterator();正因为如此,在JDKList接口中不得不增加对listIterator()方法的声明,该方法可以返回一个ListIterator类型的迭代器,ListIterator迭代器具有更加强大的功能。

反思:

应用场景:

  1. 需要(多种方式)遍历某个聚合对象,并且要求隐藏遍历细节。
  2. 对遍历对象需要进行,访问与控制分离。(可以理解为读写分离)
  3. 对客户端访问时提供统一的访问接口,聚合对象的结构差异不会影响客户端调用。

优点:

  1. 遍历的方法可定义多个,进而由不同的迭代器实现类完成即可。客户端保持统一调用方式。
  2. 对聚合对象的访问与控制进行了职责分离,简化了聚合对象的设计。
  3. 客户端面向接口编程,符合“开闭原则”。

缺点:

  1. 迭代器模式的实现过程需要大量的interface,class支撑。增删某个聚合类型都需要新增一组迭代器实现。其实现过程可能较为复杂。
  2. 完整的迭代功能较为复杂,在设计时,需要充分考虑未来的需求场景,错误的设计实现过程,很可能对性能,安全产生不利影响。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---迭代器模式 结束


特别备注:上文中关于JDK源码的描述与List结构图,可能与当前JDK8版本有分歧。建议各位看官最好能够Debug跟踪学习。


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值