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


