本篇文章介紹一種設(shè)計模式——迭代器模式。本篇文章內(nèi)容參考:《JAVA與模式》之迭代子模式桦沉, 23種設(shè)計模式(13):迭代器模式
一际度、迭代器模式定義
迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內(nèi)部的表示尸饺。把游走的任務(wù)放在迭代器上,而不是聚合上助币。這樣簡化了聚合的接口和實現(xiàn)浪听,也讓責任各得其所。
二眉菱、迭代器模式結(jié)構(gòu)
迭代器模式涉及到以下幾個角色:
● 抽象迭代器(Iterator)角色:此抽象角色定義出遍歷元素所需的接口迹栓。
● 具體迭代器(ConcreteIterator)角色:此角色實現(xiàn)了Iterator接口,并保持迭代過程中的游標位置俭缓。
● 聚集(Aggregate)角色:此抽象角色給出創(chuàng)建迭代器(Iterator)對象的接口克伊。
● 具體聚集(ConcreteAggregate)角色:實現(xiàn)了創(chuàng)建迭代器(Iterator)對象的接口,返回一個合適的具體迭代器實例华坦。
● 客戶端(Client)角色:持有對聚集及其迭代器對象的引用愿吹,調(diào)用迭代子對象的迭代接口,也有可能通過迭代子操作聚集元素的增加和刪除惜姐。
抽象聚集角色類犁跪,這個角色規(guī)定出所有的具體聚集必須實現(xiàn)的接口。迭代器模式要求聚集對象必須有一個工廠方法歹袁,也就是createIterator()方法耘拇,以向外界提供迭代器對象的實例。
public abstract class Aggregate {
/**
* 工廠方法宇攻,創(chuàng)建相應(yīng)迭代子對象的接口
*/
public abstract Iterator createIterator();
}
具體聚集角色類惫叛,實現(xiàn)了抽象聚集角色類所要求的接口,也就是createIterator()方法逞刷。此外嘉涌,還有方法getElement()向外界提供聚集元素妻熊,而方法size()向外界提供聚集的大小等。
public class ConcreteAggregate extends Aggregate {
private Object[] objArray = null;
/**
* 構(gòu)造方法仑最,傳入聚合對象的具體內(nèi)容
*/
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;
//內(nèi)部索引扔役,記錄當前迭代到的索引位置
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"};
//創(chuàng)建聚合對象
Aggregate agg = new ConcreteAggregate(objArray);
//循環(huán)輸出聚合對象中的值
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();
}
}
三、迭代器模式的應(yīng)用
如果要問Java中使用最多的一種模式警医,答案不是單例模式亿胸,也不是工廠模式,更不是策略模式预皇,而是迭代器模式侈玄,先來看一段代碼吧:
public static void print(Collection coll){
Iterator it = coll.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
這個方法的作用是循環(huán)打印一個字符串集合,里面就用到了迭代器模式吟温,java語言已經(jīng)完整地實現(xiàn)了迭代器模式序仙,例如List,Set鲁豪,Map潘悼,而迭代器的作用就是把容器中的對象一個一個地遍歷出來。
四爬橡、迭代器模式的優(yōu)缺點
優(yōu)點
①簡化了遍歷方式治唤,對于對象集合的遍歷,還是比較麻煩的糙申,對于數(shù)組或者有序列表肝劲,我們尚可以通過游標來取得,但用戶需要在對集合了解很清楚的前提下郭宝,自行遍歷對象辞槐,但是對于hash表來說,用戶遍歷起來就比較麻煩了粘室。而引入了迭代器方法后榄檬,用戶用起來就簡單的多了。
②可以提供多種遍歷方式衔统,比如說對有序列表鹿榜,我們可以根據(jù)需要提供正序遍歷,倒序遍歷兩種迭代器锦爵,用戶用起來只需要得到我們實現(xiàn)好的迭代器舱殿,就可以方便的對集合進行遍歷了。
③封裝性良好险掀,用戶只需要得到迭代器就可以遍歷沪袭,而對于遍歷算法則不用去關(guān)心。
缺點
對于比較簡單的遍歷(像數(shù)組或者有序列表)樟氢,使用迭代器方式遍歷較為繁瑣冈绊,大家可能都有感覺侠鳄,像ArrayList,我們寧可愿意使用for循環(huán)和get方法來遍歷集合死宣。
五伟恶、迭代器的應(yīng)用場景
迭代器模式是與集合共生共死的,一般來說毅该,我們只要實現(xiàn)一個集合博秫,就需要同時提供這個集合的迭代器,就像java中的Collection眶掌,List挡育、Set、Map等畏线,這些集合都有自己的迭代器。假如我們要實現(xiàn)一個這樣的新的容器良价,當然也需要引入迭代器模式寝殴,給我們的容器實現(xiàn)一個迭代器。
但是明垢,由于容器與迭代器的關(guān)系太密切了蚣常,所以大多數(shù)語言在實現(xiàn)容器的時候都給提供了迭代器,并且這些語言提供的容器和迭代器在絕大多數(shù)情況下就可以滿足我們的需要痊银,所以現(xiàn)在需要我們自己去實踐迭代器模式的場景還是比較少見的抵蚊,我們只需要使用語言中已有的容器和迭代器就可以了。