迭代器设计模式 --提供一种方法顺序访问聚合集合里面的元素,而又不暴露其内部的表示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); } }
因此总结了一下咱们程序员作的结果,就是减轻了女招待的工做,嗯,这个很重要,外加不易暴露店里面的内部信息。。。而且易维护和扩展。。。