23種設計模式之迭代器模式

卡奴達摩的專欄發表於2015-04-06

定義:提供一種方法訪問一個容器物件中各個元素,而又不暴露該物件的內部細節。

型別:行為類模式

類圖:

23種設計模式(13):迭代器模式

如果要問java中使用最多的一種模式,答案不是單例模式,也不是工廠模式,更不是策略模式,而是迭代器模式,先來看一段程式碼吧:

public static void print(Collection coll){
	Iterator it = coll.iterator();
	while(it.hasNext()){
		String str = (String)it.next();
		System.out.println(str);
	}
}

這個方法的作用是迴圈列印一個字串集合,裡面就用到了迭代器模式,java語言已經完整地實現了迭代器模式,Iterator翻譯成漢語就是迭代器的意思。提到迭代器,首先它是與集合相關的,集合也叫聚集、容器等,我們可以將集合看成是一個可以包容物件的容器,例如List,Set,Map,甚至陣列都可以叫做集合,而迭代器的作用就是把容器中的物件一個一個地遍歷出來。

迭代器模式的結構

  • 抽象容器:一般是一個介面,提供一個iterator()方法,例如java中的Collection介面,List介面,Set介面等。
  • 具體容器:就是抽象容器的具體實現類,比如List介面的有序列表實現ArrayList,List介面的連結串列實現LinkList,Set介面的雜湊列表的實現HashSet等。
  • 抽象迭代器:定義遍歷元素所需要的方法,一般來說會有這麼三個方法:取得第一個元素的方法first(),取得下一個元素的方法next(),判斷是否遍歷結束的方法isDone()(或者叫hasNext()),移出當前物件的方法remove(),
  • 迭代器實現:實現迭代器介面中定義的方法,完成集合的迭代。

程式碼實現

interface Iterator {
	public Object next();
	public boolean hasNext();
}
class ConcreteIterator implements Iterator{
	private List list = new ArrayList();
	private int cursor =0;
	public ConcreteIterator(List list){
		this.list = list;
	}
	public boolean hasNext() {
		if(cursor==list.size()){
			return false;
		}
		return true;
	}
	public Object next() {
		Object obj = null;
		if(this.hasNext()){
			obj = this.list.get(cursor++);
		}
		return obj;
	}
}
interface Aggregate {
	public void add(Object obj);
	public void remove(Object obj);
	public Iterator iterator();
}
class ConcreteAggregate implements Aggregate {
	private List list = new ArrayList();
	public void add(Object obj) {
		list.add(obj);
	}

	public Iterator iterator() {
		return new ConcreteIterator(list);
	}

	public void remove(Object obj) {
		list.remove(obj);
	}
}
public class Client {
	public static void main(String[] args){
		Aggregate ag = new ConcreteAggregate();
		ag.add("小明");
		ag.add("小紅");
		ag.add("小剛");
		Iterator it = ag.iterator();
		while(it.hasNext()){
			String str = (String)it.next();
			System.out.println(str);
		}
	}
}

上面的程式碼中,Aggregate是容器類介面,大家可以想象一下Collection,List,Set等,Aggregate就是他們的簡化版,容器類介面中主要有三個方法:新增物件方法add、刪除物件方法remove、取得迭代器方法iterator。Iterator是迭代器介面,主要有兩個方法:取得迭代物件方法next,判斷是否迭代完成方法hasNext,大家可以對比java.util.List和java.util.Iterator兩個介面自行思考。

迭代器模式的優缺點

迭代器模式的優點有:

  • 簡化了遍歷方式,對於物件集合的遍歷,還是比較麻煩的,對於陣列或者有序列表,我們尚可以通過遊標來取得,但使用者需要在對集合瞭解很清楚的前提下,自行遍歷物件,但是對於hash表來說,使用者遍歷起來就比較麻煩了。而引入了迭代器方法後,使用者用起來就簡單的多了。
  • 可以提供多種遍歷方式,比如說對有序列表,我們可以根據需要提供正序遍歷,倒序遍歷兩種迭代器,使用者用起來只需要得到我們實現好的迭代器,就可以方便的對集合進行遍歷了。
  • 封裝性良好,使用者只需要得到迭代器就可以遍歷,而對於遍歷演算法則不用去關心。

迭代器模式的缺點:

  • 對於比較簡單的遍歷(像陣列或者有序列表),使用迭代器方式遍歷較為繁瑣,大家可能都有感覺,像ArrayList,我們寧可願意使用for迴圈和get方法來遍歷集合。

迭代器模式的適用場景

迭代器模式是與集合共生共死的,一般來說,我們只要實現一個集合,就需要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實現一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現一個迭代器。

但是,由於容器與迭代器的關係太密切了,所以大多數語言在實現容器的時候都給提供了迭代器,並且這些語言提供的容器和迭代器在絕大多數情況下就可以滿足我們的需要,所以現在需要我們自己去實踐迭代器模式的場景還是比較少見的,我們只需要使用語言中已有的容器和迭代器就可以了。

相關文章