跳到主要內容
黯羽輕揚每天積累一點點

設計模式之迭代器模式(Iterator Pattern)

免費2015-03-07#Design_Pattern#迭代器模式#Iterator Pattern

迭代器模式是一種比較簡單的模式,說白了就是用迭代器來封裝遍歷細節。集合對象大都支持遍歷操作(如 Array,List,Set,Map 等等),但由於各個集合對象內部實現方式不同,遍歷時需要調用的接口也不同,迭代器就是為了給集合對象提供一個統一的接口以支持遍歷操作。

no_mkd

一.什麼是迭代器模式?

用迭代器來封裝集合對象的遍歷細節,使調用者能夠通過統一的接口來實現對集合的遍歷

迭代器也給集合對象提供了一定的保護,想要遍歷集合,直接調用迭代器的方法就好了,我們不知道也不必知道集合內部的數據管理方式

二.舉個例子

假設現有一組自定義對象,我們並不知道它們是用什麼集合對象來維護的,可能是 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 提供提供的迭代器接口幾乎可以滿足我們的需要了)

但迭代器與組合模式結合起來,可以做一些不可思議的事情(在組合模式中會作詳細介紹,點我跳轉>>

評論

暫無評論,快來發表你的看法吧

提交評論