Java设计模式——迭代器模式
概述
? 網(wǎng)上大部分人說迭代模式的時候,總是以某一種可遍歷的對象為例進行介紹。這是可行的,這也是迭代模式的基本原型。當我看到《Head Frist設計模式》中迭代模式的時候,感覺要是能從另一個角度來說明,可能更能夠體現(xiàn)迭代模式的威力所在。
? 本文介紹的這種迭代模式,倒是更像是適配器-迭代器模式。希望于你有益~
?
版權說明
著作權歸作者所有。
商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權,非商業(yè)轉(zhuǎn)載請注明出處。
作者:Q-WHai
發(fā)表日期: 2016年3月4日
鏈接:https://qwhai.blog.csdn.net/article/details/50799562
來源:CSDN
更多內(nèi)容:分類 >> 設計模式
?
模式說明
? 網(wǎng)上大多數(shù)關于迭代器模式的文章,討論都是建立在一個List或是其他可迭代對象之上的。這樣有一個問題,因為都是可迭代的對象,在迭代的過程中我們無法深入了解到迭代器模式能夠為我們解決什么樣的問題。下面有一個實例,通過這個實例可能可以說明迭代器模式的威力。
1.實例背景
? 有兩家餐廳A和B,餐廳A是一家早餐餐廳店,而餐廳B是一家午餐餐廳店。
? 現(xiàn)在兩個餐廳的大Boss決定將兩家餐廳進行合并。在餐廳A中,菜單的邏輯實現(xiàn)是基于ArrayList的,而餐廳B的菜單邏輯實現(xiàn)則是基于數(shù)組的。如果去修改任何一家餐廳的菜單實現(xiàn),都可能會引發(fā)一些不必要的修改,且這種修改可能還會導致不必要的Bug,所以A和B都不愿意去修改菜單的原始實現(xiàn)。
? 現(xiàn)在的需求是,在不改變兩家餐廳對菜單的實現(xiàn)上,再方便地對菜單進行遍歷。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -- 摘自《Head Frist設計模式》
2.思路分析
? 這個有什么難的?ArrayList和數(shù)組都是可循環(huán)遍歷的對象,那么我們不是可以依次對這兩個數(shù)組進行循環(huán)遍歷么?
? 不可否認,這是一種最為樸素的實現(xiàn)邏輯,而且易懂。可是,這種方式真的是好的么?如果現(xiàn)在有100家餐廳呢?我們希望的是能夠更方便、更優(yōu)雅地進行遍歷菜單,我們希望在后期的項目中,代碼的維護性更高,而不是一直“爛”下去。
? 我們想如果我們的ArrayList和數(shù)組可以有一個公共的接口,那么我們就可以通過這個公共的接口進行迭代,這樣一來代碼的復用性豈不是更高了么?可是,如何找到這樣的一個接口呢?在學習《Effective Java》這本神書的“類和接口”一單時,就了解到我們的程序中,復合優(yōu)于繼承。所以,這里我們可以將ArrayList和數(shù)組分別組合到不同的菜單中去,這樣對菜單的遍歷就是對ArrayList或是數(shù)組的遍歷。
? 因為ArrayList自身就包含了迭代器,所以這里我們不需要為ArrayList創(chuàng)建迭代器。而在數(shù)組中則沒有這樣的迭代邏輯,所以我們要為數(shù)組額外創(chuàng)建迭代器。
?
3.類圖
? 根據(jù)上面的分析,我們可以畫出如下類圖:
圖-1 迭代器模式類圖
4.邏輯實現(xiàn)
(1)公共接口編寫
? 在類圖中的第一個位置就留給了Menu這個接口了,添加此接口的目的在于提高代碼的可復用性。這一點在第(4)點迭代邏輯中會有所體現(xiàn)。公共接口代碼如下:
?
public interface Menu {public Iterator<MenuItem> createIterator(); }?
(2)迭代器的創(chuàng)建
? 在上面的類圖中我們可以找到BreakfastMenu和LunchMenu兩個菜單類,它們都是實現(xiàn)了Menu接口的。可是,因為它們包含了不同的容器對象(BreakfastMenu包含了ArrayList,LunchMenu包含了數(shù)組),所以在創(chuàng)建迭代器的時候就會有所不同。
? 先來看看BreakfastMenu創(chuàng)建迭代器的邏輯代碼吧,如下:
?
@Overridepublic Iterator<MenuItem> createIterator() {return menuItems.iterator();}? 因為ArrayList自身就包含了迭代器的實現(xiàn),所以這里就可以直接返回ArrayList的迭代器。而數(shù)組沒有迭代器的實現(xiàn)部分,所以與上面的創(chuàng)建方式會有所不同,如下:
?
@Overridepublic Iterator<MenuItem> createIterator() {return new LunchIterator(menuItems);}?
(3)自定義迭代器
? 由于數(shù)組本身不具備迭代的功能,所以我們就需要對其進行擴展。可是,如果想要“迭代”數(shù)組,其根本實現(xiàn)還是要依賴于數(shù)組的循環(huán)遍歷。因為數(shù)組只有這一種方式可以依次提取元素。在迭代器中有兩個核心方法:hasNext()和next()。所以,我們就利用這兩個方法變相實現(xiàn)對數(shù)組的迭代。代碼如下:
?
public class LunchIterator implements Iterator<MenuItem> {private MenuItem[] menuItems = null;private int position = 0;public LunchIterator(MenuItem[] _menuItems) {this.menuItems = _menuItems;}@Overridepublic boolean hasNext() {if (menuItems == null) {return false;}return position < menuItems.length;}@Overridepublic MenuItem next() {MenuItem menuItem = menuItems[position];position++;return menuItem;} }? 這里有一個額外定義的變量position,它是用來進行元素索引的,我們需要通過此變量提取元素,和判別迭代完成。
?
?
?
(4)迭代邏輯
? 這里說的迭代邏輯是針對迭代器之外,客戶端的實現(xiàn)邏輯。假定我們有一個女服務員,她可以打印出客戶所需要的菜單,而不用關心此菜單的實現(xiàn)方式。
?
public class Waitress {private Iterator<MenuItem> iterator = null;private Menu menu = null;public Waitress(Menu _menu) {this.menu = _menu;}public void printMenu() {System.out.println("\n菜單:");iterator = menu.createIterator();do {System.out.println(iterator.next());} while (iterator.hasNext());} }?
Ref
- 《Head Frist設計模式》
- 《23種Java設計模式》
?
Github源碼下載
https://github.com/qwhai/design-pattern
?
征集
如果你也需要使用ProcessOn這款在線繪圖工具,可以使用如下邀請鏈接進行注冊:
https://www.processon.com/i/56205c2ee4b0f6ed10838a6d
總結
以上是生活随笔為你收集整理的Java设计模式——迭代器模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式——原型模式
- 下一篇: Java设计模式——桥模式