設計模式之迭代器模式

王若伊_恩赐解脱發表於2024-08-31

迭代器模式很多人都熟悉,但是什麼是迭代器,為什麼要用迭代器?
這個很多人就很難做出具體回答了,只是知道如果有了迭代器,那麼我們就能foreach遍歷了,方便迴圈處理。
這只是對迭代器的用途,進行了回答,foreach語法是java1.5時加入的語法糖,那麼在這之前呢,之前是怎麼做的?
要知道並不是所有容器都支援以索引位置的形式,來獲取某個具體位置的元素,那麼對於這種無序的容器當時怎麼遍歷呢?
這就要說到迭代器模式了
迭代器模式就是你不需要了解容器內部資料儲存的細節,就可以依次的,按照某種順序獲取完容器裡邊的元素。

迭代器模式(Iterator Pattern)是物件導向的23種設計模式中的一種,屬於行為模式的範圍。
而在java中,已經開好預設的介面,你只需要按照介面的約定來實現對應的方法即可:
類圖如下:

我們按照要求寫一份實現程式碼,與以往容器不同的是,資料雖然只存了一份,但是我們要求遍歷的時候,每份資料我都能遍歷若干份:

容器類、迭代器類

 1 package com.example.demo.learn.pattern.behavior.iter;
 2 
 3 import java.util.Iterator;
 4 
 5 /**
 6  * @discription
 7  */
 8 public class FixCollection<T> implements Iterable<T> {
 9     Object[] data;
10 
11     int max;
12 
13     int cur = 0;
14 
15     int loop = 0;
16 
17     public FixCollection(int max, int loop) {
18         this.max = max;
19         data = new Object[max];
20         this.loop = loop;
21     }
22 
23     public boolean addData(T t) {
24         if (cur < max) {
25             data[cur++] = t;
26             return true;
27         }
28         return false;
29     }
30 
31 
32     @Override
33     public Iterator<T> iterator() {
34         return new LoopIterator();
35     }
36 
37     class LoopIterator implements Iterator<T> {
38         // 索引位置:
39         int index = 0;
40 
41 
42         public LoopIterator() {
43         }
44 
45         public boolean hasNext() {
46             return cur * loop >= (index + 1);
47         }
48 
49         public T next() {
50             int i = index++ % cur;
51             return (T) data[i];
52         }
53     }
54 }

主類

 1 package com.example.demo.learn.pattern.behavior.iter;
 2 
 3 import lombok.extern.slf4j.Slf4j;
 4 
 5 import java.util.Iterator;
 6 
 7 /**
 8  * @discription
 9  */
10 
11 @Slf4j
12 public class IterMain {
13     public static void main(String[] args) {
14         FixCollection<String> collection = new FixCollection(4, 3);
15         collection.addData("1a");
16         collection.addData("2a");
17         collection.addData("3a");
18         collection.addData("4a");
19         collection.addData("5a");
20         Iterator<String> iter = collection.iterator();
21         int i = 0;
22         while (iter.hasNext()) {
23             log.warn("iter element is {}:{}", i++, iter.next());
24         }
25 
26         int j = 0;
27         for (String item : collection) {
28             log.warn("for element is {}:{}", j++, item);
29         }
30     }
31 }

呼叫結果如下:(防盜連線:本文首發自http://www.cnblogs.com/jilodream/ )

16:51:57.870 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 0:1a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 1:2a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 2:3a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 3:4a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 4:1a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 5:2a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 6:3a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 7:4a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 8:1a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 9:2a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 10:3a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - iter element is 11:4a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 0:1a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 1:2a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 2:3a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 3:4a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 4:1a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 5:2a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 6:3a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 7:4a
16:51:57.873 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 8:1a
16:51:57.874 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 9:2a
16:51:57.874 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 10:3a
16:51:57.874 [main] WARN com.example.demo.learn.pattern.behavior.iter.IterMain - for element is 11:4a

主要的步驟是這樣的:

1、我們自定義的容器,實現Iterable介面,表示自定義容器支援返回一個迭代器。
2、我們返回的迭代器,實現Iterator 介面,支援迭代器的基本方法(還有沒有下一個元素 hasNext(),以及返回下一個元素next())。

這樣我們就可以使用迭代器了,也可以像示例那樣使用foreach語法糖 來遍歷,由編譯器幫我完成相對晦澀的轉寫。
這時候有人就問了,這個迭代器模式有點太死板了,我的容器類直接支援依次的返回物件,還算迭代器模式麼?(防盜連線:本文首發自http://www.cnblogs.com/jilodream/ )
答案是算,只要你的容器不暴露具體資料,並且支援依次的返回資料元素,就算是迭代器模式。只是你現在將容器和迭代器的功能合為一體了,容器還要維護外界的訪問狀態,相對來說不如官方約定的那麼優雅。
不要把設計模式想的過於複雜、刻板,其實我們在按照物件導向原則處理問題時,就已經在有意無意的使用各種設計模式了。

相關文章