zoukankan      html  css  js  c++  java
  • 设计模式之迭代器模式(Iterator Pattern)

    一.什么是迭代器模式?

    用迭代器来封装集合对象的遍历细节,使调用者能够通过统一的接口来实现对集合的遍历

    迭代器也给集合对象提供了一定的保护,想要遍历集合,直接调用迭代器的方法就好了,我们不知道也不必知道集合内部的数据管理方式

    二.举个例子

    假设现有一组自定义对象,我们并不知道它们是用什么集合对象来维护的,可能是Array,List或者其它。而我们的工作是遍历这组对象(或者在遍历的基础上添一些额外处理)

    想想我们要如何实现?

    首先判断集合对象的类型,再分别作以不同处理

    对于每一个不同集合类型,我们都需要一个不同的循环来处理,虽然这些循环块只有细微的差别,但我们也不得不提供一个循环去处理

    。。如果有100种不同的集合类型,我们可能就必须用100个彼此差不多的循环去实现遍历,无疑存在大篇幅的冗余代码

    所以我们需要一个统一的入口,希望把n个循环变成一个适应性很强的循环

    那么迭代器就是我们朝思暮想的那个统一入口:

    迭代器接口

    package IteratorPattern;
    
    /**
     * @author ayqy
     * 定义迭代器
     */
    public interface Iterator {
    	
    	/**
    	 * @return 集合内是否存在下一个元素
    	 */
    	public abstract boolean hasNext();
    	/**
    	 * @return 返回集合内的下一个元素
    	 */
    	public abstract Object next();
    }
    

    还需要实现一些具体的迭代器来实现遍历细节:

    Array迭代器:

    package IteratorPattern;
    
    /**
     * @author ayqy
     * 实现数组迭代器
     */
    public class ArrayIterator implements Iterator{
    	MyObject[] arr;//自定义对象数组
    	int index = 0;//当前索引
    	
    	public ArrayIterator(MyObject[] arr){
    		this.arr = arr;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(index < arr.length && arr[index] != null)
    			return true;
    		
    		return false;
    	}
    
    	@Override
    	public Object next() {
    		MyObject mo = arr[index];
    		index++;
    		
    		return mo;
    	}
    }
    

    P.S.注意Array迭代器的hasNext方法的具体实现

    List迭代器:

    package IteratorPattern;
    
    import java.util.List;
    
    /**
     * @author ayqy
     * 实现List迭代器
     */
    public class ListIterator implements Iterator{
    	List<MyObject> list;//集合对象
    	int index = 0;//当前索引
    	
    	public ListIterator(List<MyObject> list){
    		this.list = list;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(index < list.size())
    			return true;
    		
    		return false;
    	}
    
    	@Override
    	public Object next() {
    		MyObject mo = list.get(index);
    		index++;
    		
    		return mo;
    	}
    }
    

    有了这些具体迭代器,我们只需要一个循环就可以搞定了:

    /**
     * 打印集合所有内容
     * @param iter 集合的迭代器
     */
    private static void printObjs(Iterator iter){
    	while(iter.hasNext()){
    		System.out.println(iter.next().toString());
    	}
    }
    

    三.Java对Iterator的支持

    由于迭代器的方便性与必要性,Java1.5之后就提供了对Iterator的支持,目前很多集合对象都支持Iterator,例如Set, List, Map, SortedSet, SortedMap, HashSet, TreeSet, ArrayList, LinkedList, Vector等等

    唯一不支持迭代器的可能就是数组吧(栈,队列这些特殊的除外),上面我们实现了自定义的Iterator接口,其实Java本身提供这个接口(java.util.Iterator),但不同之处是:

    Java.util.Iterator接口定义了三个方法(除hasNext,next方法外还有remove方法):

    如果集合对象不愿意提供remove方法也没关系,我们可以抛出异常拒绝实现,就象这样:

    package IteratorPattern;
    
    /**
     * @author ayqy
     * 利用Java提供的Iterator接口实现数组迭代器
     */
    public class JavaArrayIterator implements java.util.Iterator{
    	MyObject[] arr;//自定义对象数组
    	int index = 0;//当前索引
    	
    	public JavaArrayIterator(MyObject[] arr){
    		this.arr = arr;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(index < arr.length && arr[index] != null)
    			return true;
    		
    		return false;
    	}
    
    	@Override
    	public Object next() {
    		MyObject mo = arr[index];
    		index++;
    		
    		return mo;
    	}
    
    	@Override
    	public void remove() {
    		//抛出操作不支持异常
    		throw new UnsupportedOperationException();
    	}
    }
    

    迭代器调用方式完全没变:

    /**
     * 打印集合所有内容
     * @param iter 集合的迭代器
     */
    private static void printObjs(java.util.Iterator iter){
    	while(iter.hasNext()){
    		System.out.println(iter.next().toString());
    	}
    }
    

    四.迭代器的隐式调用

    很多语言都支持for each(或者 for in)循环,其内部实现就是调用了迭代器完成遍历

    当然,只是一个小常识,更重要的是学会迭代器的设计原理,在需要的时候定义自己的迭代器

    五.扩展

    迭代器模式本身比较简单,甚至我们已经不需要去定义自己的迭代器了(API提供提供的迭代器接口几乎可以满足我们的需要了)

    但迭代器与组合模式结合起来,可以做一些不可思议的事情(在组合模式中会作详细介绍,点我跳转>>

  • 相关阅读:
    life
    Android通过XML来定义Menu
    Android通过XML来定义Menu
    Android开发之Menu:OptionMenu(选项菜单)、ContextMenu(上下文菜单)、SubMenu(子菜单)
    作为股权类投资人,我们的投资偏好和投资原则
    作为股权类投资人,我们的投资偏好和投资原则
    给TextView添加超链接的四种方式
    详解ExplosionField的使用,实现View的粉碎效果
    MySql中允许远程连接
    我的投资案例(3)-看好互联网和金融两大朝阳行业,参投入股垂直金融招聘平台"职业梦CareerDream.cn"
  • 原文地址:https://www.cnblogs.com/ayqy/p/3996524.html
Copyright © 2011-2022 走看看