自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

設(shè)計(jì)模式系列之迭代器模式

開發(fā) 前端
迭代器設(shè)計(jì)模式在我們業(yè)務(wù)場景中自己寫的代碼中 我個(gè)人是覺得比較少見的,至少到目前我還沒有怎么發(fā)現(xiàn)有好的業(yè)務(wù)場景可以用這個(gè)模式,所以這里我就不給大家舉例業(yè)務(wù)代碼改造了。

[[406817]]

 Iterator大家應(yīng)該都很熟悉了,作為Java程序員的我們來說,遍歷集合這也是我們剛開始學(xué)習(xí)Java知識(shí)。

遍歷集合的方式也有很多,比如for循環(huán)、while循環(huán)、foreach循環(huán)、Iterator等。這里的Iterator就是我們?cè)O(shè)計(jì)模式里面的迭代器模式。

這次要跟大家分享的設(shè)計(jì)模式就是這迭代器模式,雖然很多語言都直接把Iterator封裝到基礎(chǔ)工具類中,但是它的特性你都了解嗎?

本期大綱

定義

迭代器大家都很熟悉,那么什么叫迭代器?它的目的又是什么呢?

  • 定義:我們可以用相同的方式處理集合,無論它是列表還是數(shù)組,它都提供了一種迭代其元素而不用暴露其內(nèi)部結(jié)構(gòu)的機(jī)制,更重要的是,不同的類型的集合都可以使用相同的統(tǒng)一機(jī)制,這種機(jī)制則被稱為 迭代器模式。
  • 目的:提供一種順序遍歷聚合對(duì)象元素,而不暴露其內(nèi)部實(shí)現(xiàn)的方法。

以上定義來之設(shè)計(jì)模式之美

解析圖:

  • Aggregate(抽象容器):負(fù)責(zé)提供創(chuàng)建具體迭代器角色的接口,對(duì)應(yīng)于java.util.Collection接口。
  • Iterator(抽象迭代器):迭代器的抽象類,它定義遍歷容器對(duì)象的操作以及返回對(duì)象的操作
  • ConcreteAggregate(具體容器):主要是可以實(shí)現(xiàn)內(nèi)部不同的結(jié)構(gòu)。但會(huì)暴露處理遍歷容器的具體迭代器。
  • ConcreteIterator(具體迭代器):處理特定的具體容器類的具體迭代器,實(shí)際上對(duì)于每個(gè)容器具體容器,都必須實(shí)現(xiàn)一個(gè)具體的迭代器。

整個(gè)圖看起來其實(shí)就兩個(gè)東西,一個(gè)容器,一個(gè)迭代器。

代碼實(shí)現(xiàn)

這次就不舉列了。直接手寫一個(gè)迭代器,我們?cè)贉y試一下。

主要還是理解迭代器到底是干嘛用的:

  • 能在不暴露集合底層表現(xiàn)形式 (列表、 棧和樹等) 的情況下遍歷集合中所有的元素

話不多說,還是直接上手?jǐn)]代碼

  1. public interface Aggregate { 
  2.     // 添加元素 
  3.     void add(Object object); 
  4.  
  5.     // 移除元素 
  6.     void remove(Object object); 
  7.  
  8.     // 迭代器 
  9.     Iterator iterator(); 

按照上面的類圖,先是創(chuàng)建抽象容器,定義幾個(gè)基本添加刪除元素方法,以及迭代器

  1. public interface Iterator<E> { 
  2.     // 判斷容器是否有值 
  3.     boolean hasNext(); 
  4.  
  5.     // 把游標(biāo)執(zhí)向下一個(gè)指針 
  6.     void next(); 
  7.  
  8.     // 當(dāng)前遍歷的數(shù)據(jù) 
  9.     E currentItem(); 

其次 再試創(chuàng)建抽象迭代器,遍歷容器中的數(shù)據(jù)

  1. public class ConcreteAggregate implements Aggregate { 
  2.     private ArrayList arrayList = new ArrayList(); 
  3.  
  4.     @Override 
  5.     public void add(Object object) { 
  6.         this.arrayList.add(object); 
  7.     } 
  8.  
  9.     @Override 
  10.     public void remove(Object object) { 
  11.         this.arrayList.remove(object); 
  12.     } 
  13.  
  14.     @Override 
  15.     public Iterator iterator() { 
  16.         return new ConcreteIterator(this.arrayList); 
  17.     } 

開始定義我們具體的容器了,內(nèi)部定一個(gè)ArrayList容器,用來存放數(shù)據(jù),當(dāng)然這里大家也可以改成其他的容器 比如說用Vector 或者其他的 棧、 樹、 圖 等

  1. public class ConcreteIterator<E> implements Iterator<E> { 
  2.  
  3.     private int cursor; // 游標(biāo) 
  4.     private ArrayList arrayList; 
  5.  
  6.     public ConcreteIterator(ArrayList arrayList) { 
  7.         this.cursor = 0; 
  8.         this.arrayList = arrayList; 
  9.     } 
  10.  
  11.     @Override 
  12.     public boolean hasNext() { 
  13.         if (this.cursor == this.arrayList.size()) { 
  14.             return false
  15.         } 
  16.         return true
  17.     } 
  18.  
  19.     @Override 
  20.     public void next() { 
  21.         cursor++; 
  22.         System.out.println(cursor + "   cursor"); 
  23.     } 
  24.  
  25.     @Override 
  26.     public E currentItem() { 
  27.         if (cursor >= arrayList.size()) { 
  28.             throw new NoSuchElementException(); 
  29.         } 
  30.         E e = (E) arrayList.get(cursor); 
  31.         this.next(); 
  32.         return e; 
  33.     } 
  34.    
  35.    // 測試demo 
  36.     public static void main(String[] args) { 
  37.         Aggregate aggregate = new ConcreteAggregate(); 
  38.         aggregate.add("java"); 
  39.         aggregate.add("c++"); 
  40.         aggregate.add("php"); 
  41.         aggregate.add("敖丙"); 
  42.  
  43.         Iterator iterator = aggregate.iterator(); 
  44.         while (iterator.hasNext()) { 
  45.             System.out.println(iterator.currentItem()); 
  46.         } 
  47.       // 結(jié)果:1    java 
  48.       //      2     c++ 
  49.       //      3     php 
  50.       //      4     敖丙 
  51.     } 

最后就是實(shí)現(xiàn)具體的迭代器了, 在currentItem里面根據(jù)遍歷的游標(biāo),獲取數(shù)組里面的值

同時(shí)在main方法里面就是測試demo了,以上就是簡單的手?jǐn)]迭代器了。

這里面我們其實(shí)還可以有其它的各種特別的玩法,比如說怎么實(shí)現(xiàn)暫停遍歷等,只有了解內(nèi)部實(shí)現(xiàn),我們才能改造出符合當(dāng)前所需要的業(yè)務(wù)代碼。

Java中的迭代器

在Java的中也有迭代器,java.util.Iterator類以及java.util.Collection,就是典型的迭代器喝容器的列子,接下來看看具體的源碼

當(dāng)next沒有值的時(shí)候則會(huì)拋出NoSuchElementException異常信息,上面的手?jǐn)]異常也是根據(jù)這個(gè)來的

在Java中 常見的 List、Set、Queue都是extend Collection(容器),而Collection又定義迭代器Iterator,這就是能直接使用的原因了。

Java集合分析

上面我們看完了Java中的迭代器,不知道,大家注意了沒有,我們?cè)谑褂玫鞯臅r(shí)候是不能再對(duì)集合進(jìn)行增減操作的,否則就會(huì)拋出ConcurrentModificationException異常

那么問題來了,為什么會(huì)有這個(gè)異常信息呢?

看過ArrayList源碼的同學(xué)都知道底層是數(shù)據(jù)結(jié)構(gòu)中的數(shù)組結(jié)構(gòu)的,所以我們看下接下來圖結(jié)構(gòu)

假設(shè)現(xiàn)在開始在遍歷當(dāng)前這個(gè)數(shù)組,當(dāng)從第一步執(zhí)行到第二步,都是正常運(yùn)行的,假設(shè)現(xiàn)在執(zhí)行完第二步,開始走第三步時(shí)

刪除 java這個(gè)元素,數(shù)組為了保持存儲(chǔ)數(shù)據(jù)的連續(xù)性,當(dāng)刪除java數(shù)據(jù)時(shí),是會(huì)發(fā)生數(shù)組元素的遷移的。所以正常步驟3應(yīng)該是遍歷到aobing元素的變成當(dāng)前數(shù)組元素已經(jīng)是ao bing了。

導(dǎo)致了數(shù)組會(huì)發(fā)生ao bing沒有遍歷到,因?yàn)閿?shù)據(jù)遷移而丟失了。

同樣的假設(shè)在后面添加元素按照向后遷移,還能遍歷到,那如過插入的數(shù)據(jù)是在已經(jīng)遍歷的之前呢?

這樣整個(gè)遍歷就變成不可預(yù)估了。

  1. public static void main(String[] args) { 
  2.       List<String> aggregate = new ArrayList(); 
  3.       aggregate.add("java"); 
  4.       aggregate.add("c++"); 
  5.       aggregate.add("php"); 
  6.       aggregate.add("敖丙"); 
  7.       Iterator<String> iterator = aggregate.iterator(); 
  8.       while (iterator.hasNext()) { 
  9.           iterator.remove(); // 添加這行代碼 java.lang.IllegalStateException 
  10.           System.out.println(iterator.next()); 
  11.           iterator.remove(); // 正常 
  12.       } 
  13.   } 

再來看這個(gè)測試demo,同樣都是調(diào)用remove方法,不同的地方結(jié)果不一樣,這也就是剛好印證上面的圖體現(xiàn)的問題,所以要解決這個(gè)問題,要么就是遍歷的時(shí)候不允許增刪元素,要么是增刪元素之后讓遍歷報(bào)錯(cuò)。

通過上面的列子已經(jīng)了解了迭代器的原理以及實(shí)現(xiàn),大家可以根據(jù)自己所需要的場景改造迭代器,很多公司的一些自己的框架或者工具類等等都是通過現(xiàn)有框架源碼進(jìn)行改造而來。

迭代器的優(yōu)點(diǎn):

  • 迭代器模式封裝集合內(nèi)部的復(fù)雜數(shù)據(jù)結(jié)構(gòu),不用關(guān)心需要遍歷的對(duì)象。
  • 符合單一職責(zé)原則以及開閉原則
  • 可以對(duì)遍歷進(jìn)行把控暫?;蛘呃^續(xù)

總結(jié)

迭代器設(shè)計(jì)模式在我們業(yè)務(wù)場景中自己寫的代碼中 我個(gè)人是覺得比較少見的,至少到目前我還沒有怎么發(fā)現(xiàn)有好的業(yè)務(wù)場景可以用這個(gè)模式,所以這里我就不給大家舉例業(yè)務(wù)代碼改造了。(畢竟不能因?yàn)樵O(shè)計(jì)模式而強(qiáng)行設(shè)計(jì))

跟大家分享迭代器主要是想讓大家了解Java集合遍歷怎么實(shí)現(xiàn)的,方便我們提升自己以后的看源碼的能力,以及提升自己的設(shè)計(jì)能力。

后面就再跟大家再聊聊動(dòng)態(tài)代理設(shè)計(jì)模式,就不會(huì)再詳細(xì)講了其他的模式了,因?yàn)楸旧聿辉趺闯R姡鳛榱私膺€是會(huì)和大家做一個(gè)總結(jié)分享。

今天的迭代器模式到此結(jié)束,我是敖丙,你知道的越多,你不知道的越多,我們下期見!!!

 

責(zé)任編輯:姜華 來源: 三太子敖丙
相關(guān)推薦

2020-11-06 09:01:46

迭代器模式

2010-04-29 08:53:11

PHP迭代器模式

2021-06-09 08:53:34

設(shè)計(jì)模式策略模式工廠模式

2012-01-13 15:59:07

2020-11-09 08:20:33

解釋器模式

2021-01-21 05:34:14

設(shè)計(jì)模式建造者

2021-03-05 07:57:41

設(shè)計(jì)模式橋接

2023-09-04 13:14:00

裝飾器設(shè)計(jì)模式

2020-05-25 10:20:19

享元模式場景

2021-02-18 08:39:28

設(shè)計(jì)模式場景

2021-07-08 11:28:43

觀察者模式設(shè)計(jì)

2022-01-19 08:21:12

設(shè)計(jì)裝飾器模式

2023-12-13 13:28:16

裝飾器模式Python設(shè)計(jì)模式

2022-01-12 13:33:25

工廠模式設(shè)計(jì)

2020-10-23 09:40:26

設(shè)計(jì)模式

2020-11-03 13:05:18

命令模式

2020-11-04 08:54:54

狀態(tài)模式

2010-04-21 08:38:18

解釋器模式PHP設(shè)計(jì)模式

2020-10-19 09:28:00

抽象工廠模式

2021-09-29 13:53:17

抽象工廠模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)