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 提供提供的迭代器接口幾乎可以滿足我們的需要了)
但迭代器與組合模式結合起來,可以做一些不可思議的事情(在組合模式中會作詳細介紹,點我跳轉>>)
暫無評論,快來發表你的看法吧