這是我參與8月更文挑戰的第11天,活動詳情查看:8月更文挑戰java
歡迎來到今天的學習,今天咱們一塊兒來學習下編碼常常用到可是不會本身去實現的一種模式----迭代器模式。多嘮叨幾句,我本月將會對java的設計模式精講,歡迎點擊頭像,關注個人專欄,我會持續更新,加油!算法
系列文章:設計模式
設計模式之工廠模式markdown
設計模式之訪問者模式ide
設計模式之命令者模式post
...持續更新中
話很少說,進入正題
迭代器模式,我想你們對java.util.Iterator 應該不陌生,Iterator在java裏面被稱之爲迭代器。須要說明的是,Java Iterator(迭代器)不是一個集合,它是一種用於訪問集合的方法,可用於迭代 ArrayList 和 HashSet 等集合。
因此,看下面官方定義
迭代器模式又叫遊標(Cursor)模式,它的原始定義是:迭代器提供一種對容器對象中的各個元素進行訪問的方法,而又不須要暴露該對象的內部細節。
今天我會先簡單說明下Java Iterator(迭代器),再自行簡單實現下迭代器模式。由於在平時開發中,咱們更多的是直接使用它,不多會從零去實現一個迭代器。
可是今天咱們主要講的是迭代器模式,宗旨仍是要弄懂原理,更好的運用此模式。
Iterator接口也是Java集合框架的成員,與Collection和Map兩個系列的集合不同的是Collection和Map系列主要用於充當容器的做用,而Iterator正如其名字同樣是主要用於迭代訪問Collection集合中的元素,Iterator對象也被稱爲迭代器
該接口定義了四種方法:
能夠看到Java迭代器就是來爲各類容器提供了公共的操做接口。這樣使得對容器的遍歷操做與其具體的底層實現相隔離,達到解耦的效果。迭代器模式就是這種思想,下面咱們用自行實現一個簡單的迭代器。
先看張圖(此圖來源於網絡):
從上圖中,咱們能夠看到四種關鍵角色:
抽象集合類(Aggregate):建立和抽象迭代器類相關聯的方法,同時能夠添加其餘集合類須要的方法。
具體集合類(ConcreteAggregate):實現抽象集合類聲明的全部方法,在具體使用集合類時會建立對應具體的迭代器類
抽象迭代器類(Iterator):定義統一的迭代器方法 hasNext() 和 next(),用於判斷當前集合中是否還有對象以及按順序讀取集合中的當前對象。
具體迭代器類(ConcreteIterator):實現了抽象迭代器類聲明的方法,處理具體集合中對對象位置的偏移以及具體對象數據的傳輸。
咱們根據這套模式結合java Iterator 來自行實現 代碼以下:
//第一步 咱們也先建立一個接口迭代器 泛型
//建立抽象迭代器 IteratorIterator
public interface IteratorIterator<E> {
void reset(); //重置爲第一個元素
E next(); //獲取下一個元素
E currentItem(); //檢索當前元素
boolean hasNext(); //判斷是否還有下一個元素存在.
}
//接下來,咱們再來定義抽象集合 ListList(一樣爲了和 Java 中的 List 接口區別開),
//也聲明爲泛型接口,接收類型參數 E,聲明一個建立迭代器 IteratorIterator 的方法 iterator()。
public interface ListList<E> {
IteratorIterator<E> iterator();
}
//而後,咱們構造一個對象 Message,對象中只包含 消息體body 屬性以及其構造函數和 get、set 方法。
public class Message {
private String body;
public Topic(String body) {
super();
this.body = body;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
複製代碼
再接着實現一個具體的迭代器類 MessageIterator,其中包含屬性爲 Message 的數組和一個記錄對象存儲位置的對象 position。當咱們執行 next() 方法時,會獲取當前記錄位置的對象,至於 reset() 則會重置對象在數組中的位置爲 0,currentItem() 方法則會返回當前位置下的對象,hasNext() 則判斷當前位置是否越界。
public class MessageIterator implements IteratorIterator<Message> {
private Message[] messages;
private int position;
public MessageIterator(Message[] messages) {
this.messages = messages;
position = 0;
}
@Override
public void reset() {
position = 0;
}
@Override
public Message next() {
return messages[position++];
}
@Override
public Message currentItem() {
return messages[position];
}
@Override
public boolean hasNext() {
if(position >= messages.length) {
return false;
}
return true;
}
}
複製代碼
一樣,還須要實現一個具體的集合類 MessageList,該類中只實現一個建立迭代器的方法,返回對應具體迭代器的類方法。
public class MessageList implements ListList<Message>{
private Message[] messages;
public MessageList(Message[] messages) {
this.messages = messages;
}
@Override
public IteratorIterator<Message> iterator() {
return new MessageIterator(topics);
}
}
複製代碼
//單元測試下
public class Client {
public static void main(String[] args) {
//定義消息體,裝3條消息
Message[] messages = new Message[5];
messages[0] = new Topic("topic1");
messages[1] = new Topic("topic2");
messages[2] = new Topic("topic3");
ListList<Message> list = new MessageList(messages);
//迭代器循環
IteratorIterator<Message> iterator = list.iterator();
while(iterator.hasNext()) {
Message currentTopic = iterator.next();
System.out.println(currentTopic.getBody());
}
}
}
//輸出結果
topic1
topic2
topic3
複製代碼
OK,代碼到這裏就結束了,咱們能夠看到原理仍是比較簡單的。就是經過爲集合對象建立統一的迭代器 Iterator 來統一對集合裏的對象進行訪問
爲何使用迭代器模式?
第一個,減小程序中重複的遍歷代碼。
第二個,爲了隱藏統一遍歷集合的方法邏輯。迭代器模式把對不一樣集合類的訪問邏輯抽象出來,這樣在不用暴露集合內部結構的狀況下,能夠隱藏不一樣集合遍歷須要使用的算法,同時還可以對外提供更爲簡便的訪問算法接口。
優勢:
一、能夠減小直接使用 for 循環的重複代碼問題
二、知足開閉原則。當須要對新的對象集合進行擴展時,只須要新增具體的對象迭代器和具體的集合類便能方便地進行擴展。
缺點:
A、 增長子類數量。當新增某種集合類型的迭代器時,還得新增對應類型的迭代器和集合對象,這會增長不少不一樣的子類
感謝你的閱讀,若是你感受學到了東西,麻煩您點贊,關注。
我已經將本章收錄在專題裏,點擊下方專題,關注專欄,我會天天發表乾貨,本月我會持續輸入設計模式。
加油! 咱們下期再見!