内容简介:Design Pattern(8) - Iterator
以下文章是閱讀 深入淺出Design Pattern 還有 聖經 還有 Source making 的筆記 圖片截圖自lynda.com的 Foundations of Programming: Design Patterns 要更深入的理解一定要去看這兩本書
實作餐廳菜單
今天有一家餐廳A 想用Array來實做一個菜單
public class AMenu{ static final int MAX_ITEMS = 6; int numberOfItems = 0; String[] menuItems; public AMenu() { menuItems = new String[MAX_ITEMS]; addItem("Vegetarian BLT"); addItem("BLT"); addItem("Soup of the day"); addItem("Hotdog"); addItem("Steamed Veggies and Brown Rice"); addItem("Pasta"); } public void addItem(String name) { if (numberOfItems >= MAX_ITEMS) { System.err.println("Sorry, menu is full! Can't add item to menu"); } else { menuItems[numberOfItems] = name; numberOfItems = numberOfItems + 1; } } public String[] getMenuItems() { return menuItems; } }
今天有個服務生到餐廳A打工 當他需要列出所有選項給客人的時候 他需要這麼做
AMenu amenu = new AMenu(); for(int i = 0; i < amenu.numberOfItems; i++){ System.out.print(amenu.getMenuItems()[i]); }
這個服務生很認真 他還同時在另一家餐廳B打工 餐廳B的菜單是用ArrayList實作
public class BMenu{ ArrayList<String> menuItems; public BMenu() { menuItems = new ArrayList<String>(); addItem("K&B's Pancake Breakfast"); addItem("Regular Pancake Breakfast"); addItem("Blueberry Pancakes"); addItem("Waffles"); } public void addItem(String name) { menuItems.add(name); } public ArrayList<String> getMenuItems() { return menuItems; } }
當他需要列出所有選項給客人的時候
BMenu bmenu = new BMenu(); for(int i = 0; i < bmenu.getMenuItems().size(); i++){ System.out.print(bmenu.getMenuItems().get(i)); }
嗯…兩個不同餐廳 因為實作方法的不同 client要iterate的用法也不同 挺麻煩的 而且餐廳不一定想讓服務生知道他們的菜單是怎麼實作的(想洩露商業機密)
哎呀 那不是很簡單嗎 把printMenu跟Menu class參在一起不就行了?
每個餐廳 各自 實作自己的printMenu 這樣就不用洩漏實作的訊息給client
public class AMenu{ //other method... public void printMenu(){ for(int i = 0; i < amenu.numberOfItems; i++){ System.out.print(amenu.getMenuItems()[i]); } } } public class BMenu{ //other method... public void printMenu(){ for(int i = 0; i < bmenu.getMenuItems().size(); i++){ System.out.print(bmenu.getMenuItems().get(i)); } } }
每個餐廳的menu 各自負責printMenu 這不是解決了嗎?
這時候就要導入一個設計模式中很重要的一個概念
Design Pattern rule #6: Single Responsibility Principle(一個class只負責一件事情)
就如同字面上的意思 每個class只負責做一件事 Menu這個class就只負責addItem 不要負責printMenu
所以我們為每一個菜單 都寫一個相對應的菜單Iterator
public class AMenuIterator{ String[] items; int position = 0; public AMenuIterator(String[] items) { this.items = items; } public String next() { String menuItem = items[position]; position = position + 1; return menuItem; } public boolean hasNext() { if (position >= items.length || items[position] == null) { return false; } else { return true; } } } public class BMenuIterator { ArrayList<String> items; int position = 0; public PancakeHouseMenuIterator(ArrayList<String> items) { this.items = items; } public String next() { String menuItem = (String) items.get(position); position = position + 1; return menuItem; } public boolean hasNext() { if (position >= items.size()) { return false; } else { return true; } } }
皆大歡喜 現在我printMenu的方法可以適用所有的Iterator 我不需要知道你這家餐廳是怎麼實作你的菜單 你只要給我你的Iterator 我就有辦法print
private static void printMenu(Iterator iterator) { while (iterator.hasNext()) { String menuItem = (String)iterator.next(); System.out.println(menuItem); } }
反覆器模式
反覆器模式讓我們可以取得collection內的每一個元素 且不需要知道collection的實作
結構
-
Iterator: 制定Iterator給外界存取的interface 定義遍歷元素的方法
-
ConcreteIterator: 實作Iterator 必須記錄現在存取到哪個元素了
-
Aggregate: 可以想成是任何的Collection 但必須有個函數return 這個Collection的Iterator
-
ConcreteAggregate: 實作Aggregate createIterator函數必須傳回相對應的ConcreateIterator
優缺點
1.Iterator跟Collection分離之後 每個Collection可以有很多的Iterate方式 比如一個Tree有preorder, postorder或inorder traversal 可以愛怎麼實作多少就實作多少 Collection本身毫無負擔
2.可以同時有很多個Iterator在跑 每個Iterator會負責記得跑到哪了
3.Collection的個數和Iterator的個數會成對增加 當你今天想用LinkedList來實作你的菜單 你就需要一個LinkedList的Iterator
願上蒼為你指引平坦的道路
願命運讓你遇見善良的人們
願遠方的陽光和璀璨的燈火
為你照亮每一片未來的天空
汪峰
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。