Java 设计模式之迭代器模式
一、了解迭代器模式
1.1 什么是迭代器模式
迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。
迭代器模式把游走的任務放在迭代器上,而不是聚合上。這樣簡化了聚合的接口和實現,也可以讓責任各得其所。
1.2 迭代器模式組成結構
- 迭代器(Iterator):迭代器定義訪問和遍歷元素的接口。
- 具體迭代器(ConcreteIterator):具體迭代器實現迭代器接口,對該聚合遍歷時跟蹤當前位置。
- 聚合(Aggregate):聚合定義創建相應迭代器對象的接口。
- 具體聚合(ConcreteAggregate):具體聚合實現創建相應迭代器的接口,該操作返回 ConcreteIterator 的一個適當的實例。
1.3 迭代器模式 UML 圖解
1.4 迭代器模式適用場景
- 訪問一個聚合對象的內容而無需暴露它的內部表示。
- 支持對聚合對象的多種遍歷。
- 為遍歷不同的聚合結構提供一個統一的接口。
二、迭代器模式具體應用
2.1 問題描述
包子店與沙縣小吃合并啦:有一家包子店,他們負責提供早餐,賣各式各樣的包子,并提供豆漿之類的飲品;也有一家沙縣小吃,它們負責提供午餐和晚餐,賣一些蓋澆飯和煲仔飯。為了獲得更多的盈利,后來這兩家店合并了。
但是卻發現了一個問題,原來的包子店提供的菜單是用 List 集合結合存儲的,而沙縣小吃的菜單卻是由數組存儲的。所以在提供菜單的時候就會很麻煩,需要使用兩個不同的循環來遍歷對應的集合和數組,才能打印完整的菜單 (當然這項工作是由服務員完成的)。有沒有更好的解決辦法呢?這時候迭代器模式就登場了。
現在我們將這個問題用到代碼中去實現。
2.2 迭代器模式問題設計
2.3 代碼實現
菜單信息封裝 MenuItem 類
package com.jas.iterator;/*** 用來封裝菜單食物信息*/ public class MenuItem {String name; //食物名字double price; //食物價格public MenuItem(String name, double price){this.name = name;this.price = price;}public String getName() {return name;}public double getPrice() {return price;} }聚合 Menu 接口
package com.jas.iterator;import java.util.Iterator;public interface Menu {Iterator<MenuItem> createIterator(); }具體聚合 BZMenu 類
package com.jas.iterator;import java.util.ArrayList; import java.util.Iterator; import java.util.List;/*** 包子菜單類,實現了 Menu 接口中的 createIterator() 方法*/ public class BZMenu implements Menu{List<MenuItem> menuItems;/*** 通過構造函數,在菜單里添加一些菜品*/public BZMenu() {menuItems = new ArrayList<>();addItem("雪菜包",1.0);addItem("灌湯包",1.0);addItem("韭菜包",1.0);addItem("豬肉包",1.0);}public void addItem(String name, double price){MenuItem menuItem = new MenuItem(name, price);menuItems.add(menuItem);}/*** 返回包子菜單信息的迭代器* * @return*/@Overridepublic Iterator<MenuItem> createIterator() {return new BZMenuIterator(menuItems);} }具體聚合 SXMenu 類
package com.jas.iterator;import java.util.Iterator;/*** 沙縣菜單類,實現了 Menu 接口中的 createIterator() 方法*/ public class SXMenu implements Menu{static final int MAX_ITEMS = 4;int indexOfItems = 0;MenuItem[] menuItems;/*** 通過構造函數,在菜單里添加一些菜品*/public SXMenu(){menuItems = new MenuItem[MAX_ITEMS];addItem("青椒肉絲蓋澆飯",10.0);addItem("西紅柿雞蛋蓋澆飯",10.0);addItem("牛肉土豆煲仔飯",15.0);addItem("金針菇煲仔飯",10.0);}public void addItem(String name, double price){MenuItem menuItem = new MenuItem(name, price);if(indexOfItems >= MAX_ITEMS){System.out.println("菜單已滿!");}else {menuItems[indexOfItems] = menuItem;indexOfItems ++;}}/*** 返回沙縣菜單信息的迭代器* * @return*/@Overridepublic Iterator<MenuItem> createIterator() {return new SXMenuIterator(menuItems);} }具體迭代器 BZMenuIterator 類
package com.jas.iterator;import java.util.Iterator; import java.util.List;/*** 包子菜單信息迭代器*/ public class BZMenuIterator implements Iterator {List<MenuItem> menuItems;int position = 0;/*** 通過構造函數,實例化存儲包子信息的菜單 List 集合* 雖然可以直接使用 Iterator 來遍歷集合,為了更好理解迭代器模式,這里自己手寫一個迭代器* * @param menuItems*/public BZMenuIterator(List<MenuItem> menuItems){this.menuItems = menuItems;}@Overridepublic boolean hasNext() {if(position >= menuItems.size() || menuItems.get(position) == null){return false;}else {return true;}}@Overridepublic Object next() {MenuItem menuItem = menuItems.get(position);position += 1;return menuItem;} }具體迭代器 BZMenuIterator 類
package com.jas.iterator;import java.util.Iterator;/*** 沙縣菜單迭代器*/ public class SXMenuIterator implements Iterator {MenuItem[] menuItems;int position = 0;/*** 通過構造函數實例化存儲沙縣信息的菜單數組* * @param menuItems*/public SXMenuIterator(MenuItem[] menuItems){this.menuItems = menuItems;}@Overridepublic boolean hasNext() {if(position >= menuItems.length || menuItems[position] == null){return false;}else {return true;}}@Overridepublic Object next() {MenuItem menuItem = menuItems[position];position += 1;return menuItem;} }Waitress 類
package com.jas.iterator;import java.util.Iterator;public class Waitress {BZMenu bzMenu;SXMenu sxMenu;public Waitress(BZMenu bzMenu, SXMenu sxMenu){this.bzMenu = bzMenu;this.sxMenu = sxMenu;}public void printMenu(){Iterator<MenuItem> iterator = bzMenu.createIterator();Iterator<MenuItem> iterator1 = sxMenu.createIterator();System.out.println("包子菜單為:");printMenu(iterator);System.out.println("沙縣菜單為:");printMenu(iterator1);}private void printMenu(Iterator iterator){while (iterator.hasNext()){MenuItem menuItem = (MenuItem) iterator.next();System.out.print(menuItem.getName() + ": ");System.out.println(menuItem.getPrice());}} }測試類
package com.jas.iterator;public class MenuTestDrive {public static void main(String[] args) {BZMenu bzMenu = new BZMenu();SXMenu sxMenu = new SXMenu();Waitress waitress = new Waitress(bzMenu,sxMenu);waitress.printMenu();} }/*** 輸出* 包子菜單為:* 雪菜包: 1.0* 灌湯包: 1.0* 韭菜包: 1.0* 豬肉包: 1.0* 沙縣菜單為:* 青椒肉絲蓋澆飯: 10.0* 西紅柿雞蛋蓋澆飯: 10.0* 牛肉土豆煲仔飯: 15.0* 金針菇煲仔飯: 10.0*/2.4 問題總結
為了解決打印菜單的難題,我們新建了兩個具體迭代器,分別用于遍歷存儲包子菜單的集合和存儲沙縣菜單的數組,在包子菜單和沙縣菜單的類中提供外部可調用的遍歷菜單的迭代器。這樣一來,我們把遍歷菜單的任務放在了具體迭代器類中,而不是具體聚合類中。外部不用知道其內部菜單是如何存儲的,你只需要給外部提供一個迭代器對象,就能完成遍歷菜單的任務 。
三、 迭代器模式總結
3.1 迭代器模式優缺點總結
優點
- 它支持以不同的方式遍歷一個聚合對象。
- 迭代器簡化了聚合類。
- 在同一個聚合上可以有多個遍歷。
- 在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
缺點
對于比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較為繁瑣。
3.2 迭代器模式知識點總結
- 迭代器允許訪問聚合的元素,而不需要暴露它的內部結構。
- 迭代器將遍歷集合的任務封裝進一個對象中。
- 使用迭代器的時候,我們依賴聚合提供遍歷。
- 迭代器提供了一個通用的接口 (可以自定義也可以使用 Java API 內置的),讓我們遍歷聚合的項,當我們編碼使用聚合的項時,可以考慮使用多態機制。
PS:點擊了解更多設計模式 http://blog.csdn.net/codejas/article/details/79236013
參考文獻
《Head First 設計模式》
總結
以上是生活随笔為你收集整理的Java 设计模式之迭代器模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 设计模式之模板方法模式
- 下一篇: 厨房打印机一菜一单怎么设置?