LieBrother原文:
行爲型模式:迭代器模式java
十一大行爲型模式之六:迭代器模式。git
姓名 :迭代器模式github
英文名 :Iterator Pattern設計模式
價值觀 :人生沒有回頭路ide
我的介紹 :oop
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
它提供一種方法訪問一個容器對象中各個元素,而又不需暴露該對象的內部細節。
(來自《設計模式之禪》)this
你們夥聽歌頻率高麼?是否是常常聽歌曲來放鬆心情?我是常常會聽歌,心情很差的時候聽歌,心情好的時候也聽歌。。。今天講的迭代器模式,咱們就拿聽歌這件事來講說,你們都知道聽歌有幾種模式:單曲循環、列表循環、隨機等等。。。如今網易雲音樂還多了一個心動模式。設計
既然說到迭代器模式,那這裏就要着重講講列表循環這個聽歌模式,其餘的就先拋到腦後。在列表循環中,歌曲從第一條播放到最後一條,也就是一個遍歷歌單的過程。咱們有 2 種實現方式,一種是沒有迭代器,經過獲取歌單,用 for 循環遍歷每個歌曲,而後播放;另一種是使用迭代器,獲取歌單的一個迭代器,經過迭代器來遍歷每個歌曲,而後播放。下面咱們就用代碼來實現這 2 種方式。code
public class NoIteratorTest { public static void main(String[] args) { NetEaseMusic1 netEaseMusic1 = new NetEaseMusic1(); netEaseMusic1.listenToMusicByLoop(); } } /** * 網易雲音樂 */ class NetEaseMusic1 { private IList1 songList; public NetEaseMusic1() { songList = new SongList1(3); songList.add(new Song("讓我留在你身邊", "陳奕迅")); songList.add(new Song("你曾是少年", "SHE")); songList.add(new Song("Perfect", "Ed Sheeran")); } /** * 列表循環 */ public void listenToMusicByLoop() { for (int i = 0; i < songList.size(); i++) { System.out.println("聽歌:" + ((ISong)songList.get(i)).getSongInfo()); } } } /** * 容器接口 */ interface IList1 { void add(Object object); Object get(int index); int size(); } /** * 歌單 */ class SongList1 implements IList1 { private ISong[] songs; private int index; private int size; public SongList1(int size) { songs = new ISong[size]; index = 0; size = 0; } @Override public void add(Object object) { songs[index++] = (ISong) object; size ++; } @Override public Object get(int index) { if (index < size) { return songs[index]; } return null; } @Override public int size() { return size; } } /** * 歌曲接口 */ interface ISong { String getSongInfo(); } /** * 歌曲 */ class Song implements ISong{ private String name; private String singer; public Song(String name, String singer) { this.name = name; this.singer = singer; } @Override public String getSongInfo() { return this.name + "--" + this.singer; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSinger() { return singer; } public void setSinger(String singer) { this.singer = singer; } } 打印結果: 聽歌:讓我留在你身邊--陳奕迅 聽歌:你曾是少年--SHE 聽歌:Perfect--Ed Sheeran
咱們定義了 ISong 接口,裏面有個 getSongInfo() 方法來獲取歌曲信息,用 Song 類來定義歌曲。沒有用 Java 自帶的容器來存放歌曲,這裏實現了一個自定義容器接口 IList1,定義 SongList1 來作歌曲的容器,爲何不用 Java 自帶的 ArrayList 等等?由於 Java 自帶的已經實現了迭代器功能了,咱們這裏自定義其實就是在模仿自帶的容器的實現。NetEaseMusic1 類是充當網易雲音樂客戶端,在 listenToMusicByLoop() 方法中,咱們能夠看到是獲取了歌單 songList,而後一個一個遍歷,這是沒有使用迭代器的代碼。對象
下面看一下使用迭代器的代碼是怎麼樣的。
public class IteratorTest { public static void main(String[] args) { NetEaseMusic2 netEaseMusic2 = new NetEaseMusic2(); netEaseMusic2.listenToMusicByLoop(); } } /** * 網易雲音樂 */ class NetEaseMusic2{ private IList2 songList; public NetEaseMusic2() { songList = new SongList2(3); songList.add(new Song("讓我留在你身邊", "陳奕迅")); songList.add(new Song("你曾是少年", "SHE")); songList.add(new Song("Perfect", "Ed Sheeran")); } /** * 列表循環 */ public void listenToMusicByLoop() { IIterator iterator = songList.iterator(); while (iterator.hasNext()) { System.out.println("聽歌:" + ((ISong)iterator.next()).getSongInfo()); } } } /** * 容器接口 */ interface IList2 { IIterator iterator(); void add(Object object); Object get(int index); int size(); } /** * 歌單 */ class SongList2 implements IList2 { private ISong[] songs; private int index; private int size; public SongList2(int size) { songs = new ISong[size]; index = 0; size = 0; } @Override public IIterator iterator() { return new IteratorImpl(this); } @Override public void add(Object object) { songs[index++] = (ISong) object; size ++; } @Override public Object get(int index) { if (index < size) { return songs[index]; } return null; } @Override public int size() { return size; } } /** * 迭代器 */ interface IIterator { Object next(); boolean hasNext(); } /** * 迭代器實現類 */ class IteratorImpl implements IIterator { private IList2 list; private int index; public IteratorImpl(IList2 list) { this.list = list; this.index = 0; } @Override public Object next() { return list.get(index++); } @Override public boolean hasNext() { if (index < list.size()) { return true; } return false; } } 打印結果: 聽歌:讓我留在你身邊--陳奕迅 聽歌:你曾是少年--SHE 聽歌:Perfect--Ed Sheeran
代碼中咱們自定義了一個迭代器接口 IIterator 和迭代器具體實現類 IteratorImpl,有關鍵的 2 個方法,hasNext() 判斷是否有存在下一個元素,next() 獲取下一個元素。而 IList2 接口則比 IList1 接口多了一個獲取迭代器的方法 iterator(),這讓網易雲音樂在遍歷歌單的時候,不用直接使用 songList 來遍歷,而能夠經過 songList.iterator() 獲取迭代器來實現遍歷的過程。NetEaseMusic2.listenToMusicByLoop() 這個方法裏面就直接獲取迭代器來遍歷了。
代碼:
Iterator Pattern
迭代器模式是全部設計模式中使用最普遍的,有很多開發同窗知道迭代器,可是不知道它是設計模式的。雖然迭代器的代碼會比沒有迭代器的代碼複雜,可是加上迭代器可讓容器有統一的遍歷代碼風格,不用各自去實現遍歷方法,有更好的封裝性。在 Java 中,迭代器已經運用很普遍,好比 Java 中訪問 MySQL 獲取數據就是用迭代器來遍歷數據的。好了,迭代器模式就講到這,你們知道的知識就很少說啦。
參考資料:《大話設計模式》、《設計模式之禪》
推薦閱讀:
但願文章對您有所幫助,設計模式系列會持續更新,感興趣的同窗能夠關注公衆號:LieBrother,第一時間獲取文章推送閱讀,也能夠一塊兒交流,交個朋友。