有许多种方法能够把对象堆起来成为一个集合
好消息,当地的餐厅和煎饼屋合并了,可是二者实现的方式却不一样,这就形成了分歧。让咱们一块儿去看看把。java
一个使用ArrayList集合,另外一个使用数组实现,事情看起来确实棘手,咱们建立一个女招待做为中间人来使用两个菜单的客户代码编程
这里就有个问题,咱们在打印早餐和午饭的时候因为使用对象不一样,Arraylist和数组,这样咱们就要写两个for循环了,假若后面还有新的对象加进来作晚餐呢?或许咱们能想出一个办法,让他们的菜单实现一个相同的接口,咱们是否能够试着封装多个遍历呢?步骤图以下设计模式
OK,看来迭代器模式帮助了咱们,迭代器(iterator)依赖于迭代器接口。相关类图以下数组
想要在餐厅菜单中加入迭代器,咱们先定义迭代器接口ide
package MenuItem; /** * 迭代器接口 * * @author Joy * */ public interface Iterator { // 知道是否还有更多元素 boolean hasNext(); // 返回下一个元素 Object next(); }
而后先用DinerMenuIterator类去实现接口测试
package MenuItem; /** * 实现迭代器 * * @author Joy * */ public class DinerMenuIterator implements Iterator { MenuItem[] items; int position = 0;// 数组索引 // 构造器初始化传入一个菜单项的数组当参数 public DinerMenuIterator(MenuItem[] items) { this.items = items; } // 返回数组下一项,索引自+1 @Override public Object next() { MenuItem menuItem = items[position]; position += 1; return menuItem; } // 判断数组是否满了 @Override public boolean hasNext() { if (position >= items.length || items[position] == null) { return false; } return true; } }
咱们有了菜单迭代器,利用它改写餐厅菜单,DineMenu类中这样写this
package MenuItem; /** * 对象村餐厅 * * @author Joy * */ public class DineMenu { // 菜单总数 static final int MAX_ITEMS = 6; // 菜单量 int numberOfItems = 0; MenuItem[] menuItems; // 初始化数组,添加菜单内容 public DineMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包作", true, 2.99); addItem("BLT", "培根、生菜&西红柿", false, 2.99); addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29); addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29); addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05); } // 建立一个添加菜单方法 public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.out.println("抱歉,菜单已满,不能添加菜单了"); } else { // 菜单还没满还能够继续添加 menuItems[numberOfItems] = menuItem; numberOfItems += 1; } } // 使用迭代器遍历菜单 public Iterator createIterator() { return new DinerMenuIterator(menuItems); } }
完整代码以下spa
迭代器接口设计
package MenuItem; /** * 迭代器接口 * * @author Joy * */ public interface Iterator { // 知道是否还有更多元素 boolean hasNext(); // 返回下一个元素 Object next(); }
菜单类code
package MenuItem; /** * 对象村餐厅 * * @author Joy * */ public class DineMenu { // 菜单总数 static final int MAX_ITEMS = 6; // 菜单量 int numberOfItems = 0; MenuItem[] menuItems; // 初始化数组,添加菜单内容 public DineMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包作", true, 2.99); addItem("BLT", "培根、生菜&西红柿", false, 2.99); addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29); addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29); addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05); } // 建立一个添加菜单方法 public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.out.println("抱歉,菜单已满,不能添加菜单了"); } else { // 菜单还没满还能够继续添加 menuItems[numberOfItems] = menuItem; numberOfItems += 1; } } // 使用迭代器遍历菜单 public Iterator createIterator() { return new DinerMenuIterator(menuItems); } }
餐厅的实现以及接口
package MenuItem; /** * 实现迭代器 * * @author Joy * */ public class DinerMenuIterator implements Iterator { MenuItem[] items; int position = 0;// 数组索引 // 构造器初始化传入一个菜单项的数组当参数 public DinerMenuIterator(MenuItem[] items) { this.items = items; } // 返回数组下一项,索引自+1 @Override public Object next() { MenuItem menuItem = items[position]; position += 1; return menuItem; } // 判断数组是否满了 @Override public boolean hasNext() { if (position >= items.length || items[position] == null) { return false; } return true; } }
package MenuItem; /** * 对象村餐厅 * * @author Joy * */ public class DineMenu { // 菜单总数 static final int MAX_ITEMS = 6; // 菜单量 int numberOfItems = 0; MenuItem[] menuItems; // 初始化数组,添加菜单内容 public DineMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包作", true, 2.99); addItem("BLT", "培根、生菜&西红柿", false, 2.99); addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29); addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29); addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05); } // 建立一个添加菜单方法 public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.out.println("抱歉,菜单已满,不能添加菜单了"); } else { // 菜单还没满还能够继续添加 menuItems[numberOfItems] = menuItem; numberOfItems += 1; } } // 使用迭代器遍历菜单 public Iterator createIterator() { return new DinerMenuIterator(menuItems); } }
同理煎饼屋的实现和接口
package MenuItem; import java.util.ArrayList; public class PancakeHouseIterator implements Iterator { ArrayList items; int position = 0; public PancakeHouseIterator(ArrayList items) { this.items = items; } @Override public Object next() { Object obj = items.get(position); position += 1; return obj; } @Override public boolean hasNext() { if (position >= items.size()) { return false; } return true; } }
package MenuItem; import java.util.ArrayList; /** * 对象村煎饼屋菜单 * * @author Joy * */ public class PancakeHouseMenu { ArrayList menuItems; public PancakeHouseMenu() { menuItems = new ArrayList(); addItem("K&B薄煎饼早餐", "薄煎饼,清蛋和吐司", true, 2.99); addItem("薄煎饼早餐例餐", "薄煎饼,煎蛋和香肠", false, 2.99); addItem("蓝莓薄煎饼", "新鲜蓝莓和蓝莓糖浆作成的薄煎饼", false, 3.49); addItem("松饼", "能够选择蓝莓或草莓", true, 3.59); } // 建立一个添加菜单方法 public void addItem(String name, String description, boolean vegetarian, double price) { // 菜单项对象,并加入到ArrayList里 MenuItem menuItem = new MenuItem(name, description, vegetarian, price); menuItems.add(menuItem); } //使用迭代器遍历菜单 public Iterator createIterator(){ return new PancakeHouseIterator(menuItems); } }
女招待的实现
package MenuItem; /** * 对象村的女招待 * * @author Joy * */ public class Waitress { //建立两个餐厅对象的引用 PancakeHouseMenu pancakeHouseMenu; DineMenu dineMenu; // 初始化两个菜单 public Waitress(PancakeHouseMenu pancakeHouseMenu, DineMenu dineMenu) { this.dineMenu = dineMenu; this.pancakeHouseMenu = pancakeHouseMenu; } public void printMenu() { // 为每个菜单建立一个迭代器 Iterator pancakeitIterator = pancakeHouseMenu.createIterator(); Iterator dinerIterator = dineMenu.createIterator(); System.out.println("Menu\n=======\nBreakFast"); // 调用下面重载的方法 printMenus(pancakeitIterator); System.out.println("\nLunch"); // 调用下面重载的方法 printMenus(dinerIterator); } // 重载一个printMenu()方法 // 使用迭代器(一次循环便可)来遍历菜单项并打印出来,只调用Iterator接口 public void printMenus(Iterator iterator) { while (iterator.hasNext()) { // 取得下一项 MenuItem menuItem = (MenuItem) iterator.next(); System.out.print(menuItem.getName() + ", "); System.out.print(menuItem.getPrice() + ", "); System.out.println(menuItem.getDescription()); } } }
测试类
package TestMain; import MenuItem.DineMenu; import MenuItem.PancakeHouseMenu; import MenuItem.Waitress; public class MenuTestDrive { public static void main(String[] args) { PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); DineMenu dineMenu = new DineMenu(); /** *两个菜单都实现同样的方法,可是并无实现相同的接口, *女招待仍是要依赖两个具体实现的菜单类 *后面就要修改这里 * */ Waitress waitress = new Waitress(pancakeHouseMenu, dineMenu); waitress.printMenu(); } }
效果图以下
很巧妙的将二者迭代取出来了。但二者实现的接口却彻底同样,这里其实还能够抽象出来成一个共同接口。
感谢你看到这里,迭代器模式上部分到这里就结束了,本人文笔随便,如有不足或错误之处望给予指点,90度弯腰~~~很快我会补全这个内容,生命不息,编程不止!
参考书籍《Head First设计模式》