迭代器設計模式 --提供一種方法順序訪問聚合集合裏面的元素,而又不暴露其內部的表示java
情景 : 煎餅果子屋和普通餐廳要合併了,但又不想改變各自的菜單,如今要求一個java服務員可以按照必定的順序打印出菜單程序員
思路 : 爲了避免暴露菜單裏面的具體的內容,但又必須拿出菜單,則能夠想到迭代器的方式,其實說白了就是c中的指針。。。設計模式
咱們要作的就是送給這兩家店,每家一個迭代器,而後附送這兩家店每家一個建立迭代器的方法。。。那麼服務員就可打印這兩家菜單了數組
這是菜單項ide
package javaDesignModede_IteratorMode; public class menuItem { // 每一份菜單項的內容 private String itemName; //菜名 private String description; //描述 private boolean isVegetarian; // 是不是素食 private double price; public menuItem() { } public menuItem(String name, String des, boolean veg, double pri){ this.itemName = name; this.description = des; this.isVegetarian = veg; this.price = pri; } // 爲了避免暴露內部的信息,我就不適用getter來獲得成員變量了 @Override public String toString() { return itemName+price; } }
下面是兩家店的具體實現菜單this
package javaDesignModede_IteratorMode; import java.util.ArrayList; import java.util.Iterator; /*煎餅屋的菜單實現 * */ public class PanCakeHouseMenu { // 用一個ArrayList來實現它的菜單項 ArrayList<menuItem> menuItems; //在菜單的構造器中每一份都會被添加到菜單集合中 public PanCakeHouseMenu() { addItem("普通煎餅果子", "加上雞蛋和火腿", false, 7.5); addItem("藍莓煎餅果子", "加上藍莓", true, 5.0); addItem("華夫餅", "加上藍莓和草莓", true, 6.5); } public void addItem(String name, String des, boolean veg, double pri){ menuItem item = new menuItem(name, des, veg, pri); menuItems.add(item); } // 返回煎餅屋的菜單項 public ArrayList<menuItem> getMenuItems(){ return menuItems; } // 擁有了panCakeMenu的迭代器後,就可刪除這個暴露所有內在數據的getMenuItem()方法了 public Iterator createIterator(){ return new PanCakeHouseMenuIterator(menuItems); } }
package javaDesignModede_IteratorMode; import java.util.Iterator; /*餐廳的菜單 * */ public class DinnerMenu{ // 餐廳用的是數組,因此最大長度可定 static final int MAX_ITEMS = 6; int numberOFitems = 0; menuItem[] menuItems; // 構造菜單的方法和煎餅果子相差無幾,只是這家有數量限制 public DinnerMenu() { menuItems = new menuItem[MAX_ITEMS]; addItem("蔬菜沙拉", "用沙拉醬和番茄醬", true, 6.5); addItem("酸菜粉絲湯", "", true, 3.00); addItem("韭菜炒肉", "中份", false, 5.3); addItem("熱狗", "上面抹層芝士", false, 4.2); } public void addItem(String name, String des, boolean veg, double pri){ menuItem item = new menuItem(name, des, veg, pri); if(numberOFitems >= MAX_ITEMS){ System.out.println("對不起,菜單暫時滿了。。。今天就先提供這些吧!"); }else{ menuItems[numberOFitems] = item; numberOFitems++; } } public menuItem[] getMenuItems(){ return menuItems; } // 如今咱們擁有了餐廳的迭代器,就不須要getMenuItems() 由於它會暴露咱們內在的信息,就至關於把整個數據暴露出來,而迭代器就是一種相似於指針的東西,很好的保護了內在的數據 // 因此咱們如今只須要在菜單上增長一個方法來建立這個迭代器給客戶 public Iterator createIterator(){ return new DinnerMenuIterator(menuItems); } }
沒有迭代器的普通服務員。。。不用維護擴展,而且容易暴露內部信息spa
package javaDesignModede_IteratorMode; import java.util.ArrayList; import java.util.Iterator; /*兩家店已經合併了,如今你須要作的就是建立一個女招待,來應對顧客的須要打印一個定值的菜單,甚至告訴你這個菜單是否是素食 * 而無需詢問廚師 * * 要實現的 * printMenu() 打印菜單的每一項 * printPanCakeMenu() 打印煎餅果子的每一項 * printDinnerMenu() 打印餐廳的每一項 * printVegetarianMenu() 打印菜單裏全部的素食項 * isItemVegetarian(name) 判斷是不是素食 * */ public class Waitress { // 普通版本的女招待 ArrayList<menuItem> forPanCakeList; menuItem[] forDinnerArray; PanCakeHouseMenu panCakeHouseMenu =new PanCakeHouseMenu(); DinnerMenu dinnerMenu =new DinnerMenu(); public Waitress() { this.forPanCakeList = panCakeHouseMenu.getMenuItems(); this.forDinnerArray = dinnerMenu.getMenuItems(); } // 如今獲得PanCake菜單項展現出來 public void printPanCakeMenu(){ for (menuItem item : forPanCakeList) { System.out.println(item.toString()); } } public void printDinnerMenu(){ for(int i = 0; i<forDinnerArray.length; ++i){ System.out.println(forDinnerArray[i].toString()); } } // 如今是兩家用了不一樣的方式來存菜單,就須要兩張不一樣的遍歷方式,如果第三家也用不一樣的方式存菜單,豈不是又要遍歷一次? // 這樣的女招待很難維護,不易擴展...因此咱們選擇了進階版的女招待 }
能夠發現,上面的女招待也是很累,每入駐一家店,就要重新編寫一個遍歷的方式,不如就讓這些遍歷的方式統一實現一個接口,而後運用多態的方式,來再多家設計
都無所謂~無所謂。。。指針
如今就是送「胡利」的時間了。。。買一送一,買迭代器,送建立迭代器方法code
package javaDesignModede_IteratorMode; import java.util.ArrayList; import java.util.Iterator; public class PanCakeHouseMenuIterator implements Iterator{ // 首先選擇迭代的類型 ArrayList<menuItem> panCakeList; // 以及迭代器指向的位置記錄 int index = 0; // 而後再對構造方法進行輸入具體的迭代區域 public PanCakeHouseMenuIterator(ArrayList<menuItem> list) { this.panCakeList = list; } // 以後再覆蓋相應的方法實現迭代 public boolean hasNext() { if(index >= panCakeList.size() || panCakeList.get(index) == null){ return false; }else{ return true; } } public Object next() { menuItem item = (menuItem)panCakeList.get(index); index ++; return item; } }
package javaDesignModede_IteratorMode; /* 如今咱們須要一個迭代器來爲餐廳的菜單服務 -- 其實就是指針的應用 * */ import java.util.Iterator; public class DinnerMenuIterator implements Iterator{ // 要實現一個迭代器,首先要定義迭代的內容 menuItem[] items; // 而後是迭代器的位置變化須要一個指示器 int position = 0; // 構造器須要傳入一個該迭代器具體指向的菜單項做爲參數 public DinnerMenuIterator() { } public DinnerMenuIterator(menuItem[] items){ this.items = items; } // 而後覆蓋接口的方法 // hasNext() 是查看是否已經遍歷完全部的元素,若不是就返回true public boolean hasNext() { if(position >= items.length || items[position] == null){ return false; }else{ return true; } } // 返回下一個元素,並遞增其位置 public Object next() { menuItem item = items[position]; position ++; return item; } }
而後方法其實在上面的店裏面的菜單已經出現了 createIterator();
擁有了迭代器的服務員,進階版
package javaDesignModede_IteratorMode; import java.util.Iterator; /*兩家店已經合併了,如今你須要作的就是建立一個女招待,來應對顧客的須要打印一個定值的菜單,甚至告訴你這個菜單是否是素食 * 而無需詢問廚師 * * 要實現的 * printMenu() 打印菜單的每一項 * printPanCakeMenu() 打印煎餅果子的每一項 * printDinnerMenu() 打印餐廳的每一項 * printVegetarianMenu() 打印菜單裏全部的素食項 * isItemVegetarian(name) 判斷是不是素食 * */ public class StrongerWaitress { // 進階版的女招待--會用迭代器的女招待 PanCakeHouseMenu panCakeHouseMenu = new PanCakeHouseMenu(); DinnerMenu dinnerMenu = new DinnerMenu(); public StrongerWaitress(PanCakeHouseMenu p, DinnerMenu d) { this.panCakeHouseMenu = p; this.dinnerMenu = d; } // 打印每一項 --用通用接口實現多態 private void printMenu(Iterator iterator){ while(iterator.hasNext()){ menuItem item = (menuItem)iterator.next(); System.out.println(item.toString()); } } //下面這個方法爲每個菜單建立一個迭代器 public void printMenu(){ Iterator dinnerIterator = dinnerMenu.createIterator(); Iterator panIterator = panCakeHouseMenu.createIterator(); // 調用重載的printMenu來輸出菜單 printMenu(dinnerIterator); printMenu(panIterator); } }
因此總結了一下咱們程序員作的結果,就是減輕了女招待的工做,嗯,這個很重要,外加不易暴露店裏面的內部信息。。。而且易維護和擴展。。。