本篇文章介紹一種設計模式——迭代器模式。本篇文章內容參考:《JAVA與模式》之迭代子模式, 23種設計模式(13):迭代器模式
一、迭代器模式定義
迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。把遊走的任務放在迭代器上,而不是聚合上。這樣簡化了聚合的接口和實現,也讓責任各得其所。
二、迭代器模式結構
迭代器模式涉及到以下幾個角色:
● 抽象迭代器(Iterator)角色:此抽象角色定義出遍歷元素所需的接口。
● 具體迭代器(ConcreteIterator)角色:此角色實現了Iterator接口,並保持迭代過程中的遊標位置。
● 聚集(Aggregate)角色:此抽象角色給出創建迭代器(Iterator)對象的接口。
● 具體聚集(ConcreteAggregate)角色:實現了創建迭代器(Iterator)對象的接口,返回一個合適的具體迭代器實例。
● 客戶端(Client)角色:持有對聚集及其迭代器對象的引用,調用迭代子對象的迭代接口,也有可能通過迭代子操作聚集元素的增加和刪除。
抽象聚集角色類,這個角色規定出所有的具體聚集必須實現的接口。迭代器模式要求聚集對象必須有一個工廠方法,也就是createIterator()方法,以向外界提供迭代器對象的實例。
public abstract class Aggregate {
/**
* 工廠方法,創建相應迭代子對象的接口
*/
public abstract Iterator createIterator();
}
具體聚集角色類,實現了抽象聚集角色類所要求的接口,也就是createIterator()方法。此外,還有方法getElement()向外界提供聚集元素,而方法size()向外界提供聚集的大小等。
public class ConcreteAggregate extends Aggregate {
private Object[] objArray = null;
/**
* 構造方法,傳入聚合對象的具體內容
*/
public ConcreteAggregate(Object[] objArray){
this.objArray = objArray;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
/**
* 取值方法:向外界提供聚集元素
*/
public Object getElement(int index){
if(index < objArray.length){
return objArray[index];
}else{
return null;
}
}
/**
* 取值方法:向外界提供聚集的大小
*/
public int size(){
return objArray.length;
}
}
抽象迭代器角色類
public interface Iterator {
/**
* 迭代方法:移動到第一個元素
*/
public void first();
/**
* 迭代方法:移動到下一個元素
*/
public void next();
/**
* 迭代方法:是否爲最後一個元素
*/
public boolean isDone();
/**
* 迭代方法:返還當前元素
*/
public Object currentItem();
}
具體迭代器角色類
public class ConcreteIterator implements Iterator {
//持有被迭代的具體的聚合對象
private ConcreteAggregate agg;
//內部索引,記錄當前迭代到的索引位置
private int index = 0;
//記錄當前聚集對象的大小
private int size = 0;
public ConcreteIterator(ConcreteAggregate agg){
this.agg = agg;
this.size = agg.size();
index = 0;
}
/**
* 迭代方法:返還當前元素
*/
@Override
public Object currentItem() {
return agg.getElement(index);
}
/**
* 迭代方法:移動到第一個元素
*/
@Override
public void first() {
index = 0;
}
/**
* 迭代方法:是否爲最後一個元素
*/
@Override
public boolean isDone() {
return (index >= size);
}
/**
* 迭代方法:移動到下一個元素
*/
@Override
public void next() {
if(index < size)
{
index ++;
}
}
}
客戶端類
public class Client {
public void operation(){
Object[] objArray = {"One","Two","Three","Four","Five","Six"};
//創建聚合對象
Aggregate agg = new ConcreteAggregate(objArray);
//循環輸出聚合對象中的值
Iterator it = agg.createIterator();
while(!it.isDone()){
System.out.println(it.currentItem());
it.next();
}
}
public static void main(String[] args) {
Client client = new Client();
client.operation();
}
}
三、迭代器模式的應用
如果要問Java中使用最多的一種模式,答案不是單例模式,也不是工廠模式,更不是策略模式,而是迭代器模式,先來看一段代碼吧:
public static void print(Collection coll){
Iterator it = coll.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
這個方法的作用是循環打印一個字符串集合,裏面就用到了迭代器模式,java語言已經完整地實現了迭代器模式,例如List,Set,Map,而迭代器的作用就是把容器中的對象一個一個地遍歷出來。
四、迭代器模式的優缺點
優點
①簡化了遍歷方式,對於對象集合的遍歷,還是比較麻煩的,對於數組或者有序列表,我們尚可以通過遊標來取得,但用戶需要在對集合瞭解很清楚的前提下,自行遍歷對象,但是對於hash表來說,用戶遍歷起來就比較麻煩了。而引入了迭代器方法後,用戶用起來就簡單的多了。
②可以提供多種遍歷方式,比如說對有序列表,我們可以根據需要提供正序遍歷,倒序遍歷兩種迭代器,用戶用起來只需要得到我們實現好的迭代器,就可以方便的對集合進行遍歷了。
③封裝性良好,用戶只需要得到迭代器就可以遍歷,而對於遍歷算法則不用去關心。
缺點
對於比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較爲繁瑣,大家可能都有感覺,像ArrayList,我們寧可願意使用for循環和get方法來遍歷集合。
五、迭代器的應用場景
迭代器模式是與集合共生共死的,一般來說,我們只要實現一個集合,就需要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實現一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現一個迭代器。
但是,由於容器與迭代器的關係太密切了,所以大多數語言在實現容器的時候都給提供了迭代器,並且這些語言提供的容器和迭代器在絕大多數情況下就可以滿足我們的需要,所以現在需要我們自己去實踐迭代器模式的場景還是比較少見的,我們只需要使用語言中已有的容器和迭代器就可以了。