Design Pattern(8) - Iterator

栏目: 后端 · 发布时间: 7年前

内容简介: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參在一起不就行了?

Design Pattern(8) - Iterator

每個餐廳 各自 實作自己的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的實作

結構

Design Pattern(8) - Iterator

  • 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

願上蒼為你指引平坦的道路

願命運讓你遇見善良的人們

願遠方的陽光和璀璨的燈火

為你照亮每一片未來的天空

汪峰


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

统计学习方法

统计学习方法

李航 / 清华大学出版社 / 2012-3 / 38.00元

详细介绍支持向量机、Boosting、最大熵、条件随机场等十个统计学习方法。一起来看看 《统计学习方法》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具