Java設(shè)計模式之迭代器模式
本文介紹設(shè)計模式中的迭代器模式,首先通俗的解釋迭代器模式的基本概念和對應(yīng)的四個角色,并根據(jù)四個角色舉一個典型的實例,為了加強(qiáng)知識的連貫性,我們以Jdk源碼集合中使用迭代器模式的應(yīng)用進(jìn)一步說明,最后說明迭代器模式的應(yīng)用場景和優(yōu)缺點。
讀者可以拉取完整代碼本地學(xué)習(xí),實現(xiàn)代碼均測試通過上傳到碼云,本地源碼下載。
一、概念理解
迭代器模式官方解釋就是提供一個對象來順序訪問聚合對象中的一系列數(shù)據(jù),而不暴露聚合對象的內(nèi)部表示。何為聚合對象呢?最典型的就是集合類。
大白話也就是,集合中的數(shù)據(jù)是私有的,集合中不應(yīng)該提供直接遍歷的方法,要定義一個新的對象用于訪問這個集合。
既然是一個專門用來遍歷的對象,一個被遍歷的聚合對象,很顯然至少有兩個對象,迭代器對象、聚合對象,由于遵循面向接口編程的原則,迭代器對象和聚合對象應(yīng)該抽象出來接口,那自然而然就是應(yīng)該有四個角色:
抽象聚合(InterfaceAggregate)角色:定義存儲、添加、刪除聚合元素以及創(chuàng)建迭代器對象的接口。
具體聚合(ConcreteAggregate)角色:實現(xiàn)抽象聚合類,返回一個具體迭代器的實例。
抽象迭代器(Iterator)角色:定義訪問和遍歷聚合元素的接口,通常包含 hasNext()、next() 等方法。
具體迭代器(Concretelterator)角色:實現(xiàn)抽象迭代器接口中所定義的方法,完成對聚合對象的遍歷,記錄遍歷的當(dāng)前位置。
基于四個角色我們舉一個典型案例。
二、案例實現(xiàn)
應(yīng)該是有四個類
抽象聚合角色,用于定義增刪改查元素的統(tǒng)一規(guī)范接口,和創(chuàng)建迭代器對象的方法
具體聚合角色,實現(xiàn)抽象聚合角色方法
抽象迭代器角色,定義遍歷元素的統(tǒng)一規(guī)范接口
具體迭代器,實現(xiàn)抽象迭代器角色的方法。
抽象聚合角色:
/** * 抽象聚合角色 * @author tcy * @Date 13-09-2022 */ public interface InterfaceAggregate { /** * 增加對象 * @param obj 對象 */ void add(Object obj); /** * 移除對象 * @param obj 對象 */ void remove(Object obj); /** * 調(diào)用迭代器 * @return 迭代器 */ Iterator getIterator(); }
具體聚合角色:
/** * 具體聚合角色 * @author tcy * @Date 13-09-2022 */ public class ConcreteAggregate implements InterfaceAggregate{ private List<Object> list = new ArrayList<>(); @Override public void add(Object obj) { list.add(obj); } @Override public void remove(Object obj) { list.remove(obj); } @Override public Iterator getIterator() { return new Concretelterator(list); } }
抽象迭代器角色:
/** * 抽象迭代器 * @author tcy * @Date 13-09-2022 */ public interface Iterator<E> { /** * 刪除對象 * @return 對象 */ Object remove(); /** * 調(diào)用下一個對象 * @return 對象 */ E next(); /** * 迭代器中是否還有下一個對象 * @return */ boolean hasNext(); /** * 遍歷迭代器中剩余的對象 * @param action */ default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); } }
具體迭代器角色:
/** * 具體迭代器角色 * @author tcy * @Date 13-09-2022 */ public class Concretelterator implements Iterator{ private List<Object> list = null; private int index = -1; public Concretelterator(List<Object> list) { this.list = list; } @Override public Object remove() { index = list.size(); Object obj = list.get(index); list.remove(obj); return obj; } @Override public Object next() { Object obj = null; if (this.hasNext()) { obj = list.get(++index); } return obj; } @Override public boolean hasNext() { if (index < list.size() - 1) { return true; } else { return false; } } }
客戶端調(diào)用:
/** * @author tcy * @Date 13-09-2022 */ public class Client { public static void main(String[] args) { ConcreteAggregate concreteAggregate=new ConcreteAggregate(); concreteAggregate.add("老王"); concreteAggregate.add("小王"); concreteAggregate.add("小張"); System.out.println("Aggregate聚合對象有:"); Iterator iterator=concreteAggregate.getIterator(); while (iterator.hasNext()){ Object next = iterator.next(); System.out.println(next.toString()); } //遍歷剩下的角色 iterator.forEachRemaining(ele -> System.out.println(ele)); } }
迭代器實現(xiàn)邏輯比較清晰,理解起來難度也不大,了解了該設(shè)計模式,趁熱打鐵看迭代器模式在源碼中的應(yīng)用。
三、源碼應(yīng)用
迭代器模式在Jdk中的集合類中有著廣泛的應(yīng)用,我們以ArrayList作為典型。
在ArrayList實現(xiàn)迭代器時,同樣是有四個角色。
List抽象聚合類;
ArrayList具體聚合角色;
Iterator抽象迭代器;
ArrayList內(nèi)部類Itr是具體迭代器;
我們可以看到ArrayList是把具體聚合角色和具體迭代器都寫在一個類中,Itr作為具體迭代對象是以內(nèi)部類的形式。
ArrayList其實和我們案例中的方法長的很像,只不過ArrayList中定義了更多的方法,而且ArrayList還有一個內(nèi)部類ListItr。
其實是迭代器的增強(qiáng)版,在繼承Itr的基礎(chǔ)之上實現(xiàn)ListIterator接口。
Iterator迭代器除了,hasNext()、next()、remove()方法以外,還有一個特別的forEachRemaining()方法,我們重點說下forEachRemaining()方法,該方法代表的意思是遍歷剩下的集合。
比如我們已經(jīng)調(diào)用了該集合中的第一個元素,那么遍歷時候就會自動忽略第一個元素,遍歷剩下的元素。
我們寫一個測試方法看效果:
public class Client { public static void main(String[] args) { // jdk ArrayList迭代器 //創(chuàng)建一個元素類型為Integer的集合 Collection<String> collection = new ArrayList<>(); //向集合中添加元素 collection.add("老王"); collection.add("小王"); collection.add("小張"); //獲取該集合的迭代器 java.util.Iterator<String> iteratorJdk= collection.iterator(); System.out.println("Arraylist聚合對象有:"); //調(diào)用迭代器的經(jīng)過集合實現(xiàn)的抽象方法遍歷集合元素 while(iteratorJdk.hasNext()) { System.out.println(iteratorJdk.next()); } //調(diào)用forEachRemaining()方法遍歷集合元素 iteratorJdk.forEachRemaining(ele -> System.out.println(ele)); } }
Arraylist聚合對象有:
老王
小王
小張
正常情況下,會打印兩次集合對象中的信息,實際上只打印了一次,正是由于next調(diào)用過的元素,forEachRemaining不會再調(diào)。
看到這,想必你對迭代器已經(jīng)有了初步的了解,當(dāng)在遍歷元素時,除了使用for循環(huán)遍歷元素以外,提供了另外一種方式遍歷元素。
案例很好理解,源碼中的應(yīng)用也看得懂,但是實際開發(fā)中迭代器對象什么時候用呢?想必大部分人并不是很清晰。
接著看迭代器對象的應(yīng)用場景和優(yōu)缺點,看從中能不能找到答案。
四、總結(jié)
當(dāng)一個對象是一個聚合對象且需要對外提供遍歷方法時,可以使用迭代器模式,也即實際業(yè)務(wù)中定義的有聚合對象,里面存放了我們需要的業(yè)務(wù)數(shù)據(jù),為了讓業(yè)務(wù)數(shù)據(jù)的職責(zé)更清晰,我們就可以將編輯的方法提取出來,另外定義一個迭代器對象用于遍歷數(shù)據(jù)。
迭代器方式提供了不同的方式遍歷聚合對象,增加新的聚合類和迭代器類都是比較方便的,Java集合類中龐大的家族采用迭代器模式就是基于這種優(yōu)點。
迭代器模式有設(shè)計模式的通用缺點——系統(tǒng)復(fù)雜性,迭代器模式將數(shù)據(jù)存儲和數(shù)據(jù)遍歷分開,增加了類的個數(shù)。
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
RabbitMQ開啟SSL與SpringBoot連接測試的配置方法
本文基于 CentOS 7 + Git + OpenSSL + yum 安裝的 RabbitMQ,需要讀者提交安裝好。其他方式也可變通參考本文。對RabbitMQ開啟SSL與SpringBoot連接測試相關(guān)知識感興趣的朋友一起看看吧2022-01-01Spring?IoC容器Bean作用域的singleton與prototype使用配置
這篇文章主要為大家介紹了Spring?IoC容器Bean作用域的singleton與prototype使用配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式
這篇文章主要介紹了feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01深層剖析java應(yīng)用開發(fā)中MyBayis緩存
這篇文章主要為大家深層剖析java開發(fā)中MyBayis緩存,文中講解了Mybatis緩存的分類以及使用的方式,有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09新手小白入門必學(xué)JAVA面向?qū)ο笾鄳B(tài)
說到多態(tài),一定離不開其它兩大特性:封裝和繼承,下面這篇文章主要給大家介紹了關(guān)于新手小白入門必學(xué)JAVA面向?qū)ο笾鄳B(tài)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02SSH框架網(wǎng)上商城項目第18戰(zhàn)之過濾器實現(xiàn)購物登錄功能的判斷
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項目第18戰(zhàn):過濾器實現(xiàn)購物登錄功能的判斷,感興趣的小伙伴們可以參考一下2016-06-06Spring?Cloud?通過?Gateway?webflux實現(xiàn)網(wǎng)關(guān)異常處理
在某一個服務(wù)中出現(xiàn)異常,通過@ControllerAdvice?+?@ExceptionHandler?統(tǒng)一異常處理,即使在微服務(wù)架構(gòu)中,也可以將上述統(tǒng)一異常處理放入到公共的微服務(wù)中,這樣哪一個微服務(wù)需要,直接引入模塊,本文重點介紹Spring?Cloud?通過?Gateway?webflux實現(xiàn)網(wǎng)關(guān)異常處理,一起看看吧2023-11-11