《HeadFirst设计模式》读书笔记-第9章-迭代器模式
2017-04-24 08:26
295 查看
定义
迭代器模式(iterator pattern)提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示。迭代器模式把遍历集合内元素的操作交给了迭代器,而集合本身专注在管理元素,这符合单一责任原则,让设计具有高内聚。
代码实现
下面以JDK现有的Iterator的例子来说明适配器模式使用。给出创建Iterator接口的定义:
import java.util.Iterator; public interface Menu { public Iterator createIterator(); }
菜单项的BEAN对象:
public class MenuItem { String name; // 菜名 String description; // 描述 boolean vegetarian; // 是否是素菜 double price; // 菜单价 public MenuItem(String name, String description, boolean vegetarian, double price) { this.name = name; this.description = description; this.vegetarian = vegetarian; this.price = price; } public String getName() { return name; } public String getDescription() { return description; } public double getPrice() { return price; } public boolean isVegetarian() { return vegetarian; } }
具体集合对象,管理(增加,移除,查找等)集合的元素,实现创建Iterator接口
import java.util.ArrayList; import java.util.Iterator; public class PancakeHouseMenu implements Menu { ArrayList menuItems; // 内部存储是ArrayList public PancakeHouseMenu() { menuItems = new ArrayList(); addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99); addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99); addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries, and blueberry syrup", true, 3.49); addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); menuItems.add(menuItem); } public ArrayList getMenuItems() { return menuItems; } public Iterator createIterator() { return menuItems.iterator(); } // other menu methods here }
另一个具体集合对象,内部的存储是数组
import java.util.Iterator; public class DinerMenu implements Menu { static final int MAX_ITEMS = 6; int numberOfItems = 0; MenuItem[] menuItems; public DinerMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99); addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29); addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05); addItem("Steamed Veggies and Brown Rice", "A medly of steamed vegetables over brown rice", true, 3.99); addItem("Pasta", "Spaghetti with Marinara Sauce, and a slice of sourdough bread", true, 3.89); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.err.println("Sorry, menu is full! Can't add item to menu"); } else { menuItems[numberOfItems] = menuItem; numberOfItems = numberOfItems + 1; } } public MenuItem[] getMenuItems() { return menuItems; } // 数组需要自己实现迭代器的创建 public Iterator createIterator() { return new DinerMenuIterator(menuItems); } // other menu methods here }
数组类型的迭代器的实现:
import java.util.Iterator; // 使用JDK中迭代器接口 public class DinerMenuIterator implements Iterator { MenuItem[] list; int position = 0; public DinerMenuIterator(MenuItem[] list) { this.list = list; } public Object next() { MenuItem menuItem = list[position]; position = position + 1; return menuItem; } public boolean hasNext() { if (position >= list.length || list[position] == null) { return false; } else { return true; } } public void remove() { if (position <= 0) { throw new IllegalStateException ("You can't remove an item until you've done at least one next()"); } if (list[position-1] != null) { for (int i = position-1; i < (list.length-1); i++) { list[i] = list[i+1]; } list[list.length-1] = null; } } }
另一个具体集合对象,内部的存储是Hashtable
import java.util.*; public class CafeMenu implements Menu { Hashtable menuItems = new Hashtable(); //内部的存储是Hashtable public CafeMenu() { addItem("Veggie Burger and Air Fries", "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", true, 3.99); addItem("Soup of the day", "A cup of the soup of the day, with a side salad", false, 3.69); addItem("Burrito", "A large burrito, with whole pinto beans, salsa, guacamole", true, 4.29); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); menuItems.put(menuItem.getName(), menuItem); } public Hashtable getItems() { return menuItems; } public Iterator createIterator() { return menuItems.values().iterator(); } }
客户(招待员)代码,她持有Menu接口,通过这个接口去创建迭代器遍历菜单,她不需要知道菜单项内部的存储细节。
import java.util.Iterator; public class Waitress { Menu pancakeHouseMenu; // 煎饼屋菜单 Menu dinerMenu; // 餐厅菜单 Menu cafeMenu; // 咖啡厅菜单 public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) { this.pancakeHouseMenu = pancakeHouseMenu; this.dinerMenu = dinerMenu; this.cafeMenu = cafeMenu; } public void printMenu() { // 生成迭代器接口 Iterator pancakeIterator = pancakeHouseMenu.createIterator(); Iterator dinerIterator = dinerMenu.createIterator(); Iterator cafeIterator = cafeMenu.createIterator(); System.out.println("MENU\n----\nBREAKFAST"); printMenu(pancakeIterator); System.out.println("\nLUNCH"); printMenu(dinerIterator); System.out.println("\nDINNER"); printMenu(cafeIterator); } // 遍历迭代器,遍历所有迭代器的代码都可以复用这段代码 private void printMenu(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()); } } public void printVegetarianMenu() { System.out.println("\nVEGETARIAN MENU\n---------------"); printVegetarianMenu(pancakeHouseMenu.createIterator()); printVegetarianMenu(dinerMenu.createIterator()); printVegetarianMenu(cafeMenu.createIterator()); } public boolean isItemVegetarian(String name) { Iterator pancakeIterator = pancakeHouseMenu.createIterator(); if (isVegetarian(name, pancakeIterator)) { return true; } Iterator dinerIterator = dinerMenu.createIterator(); if (isVegetarian(name, dinerIterator)) { return true; } Iterator cafeIterator = cafeMenu.createIterator(); if (isVegetarian(name, cafeIterator)) { return true; } return false; } private void printVegetarianMenu(Iterator iterator) { while (iterator.hasNext()) { MenuItem menuItem = (MenuItem)iterator.next(); if (menuItem.isVegetarian()) { System.out.print(menuItem.getName() + ", "); System.out.print(menuItem.getPrice() + " -- "); System.out.println(menuItem.getDescription()); } } } private boolean isVegetarian(String name, Iterator iterator) { while (iterator.hasNext()) { MenuItem menuItem = (MenuItem)iterator.next(); if (menuItem.getName().equals(name)) { if (menuItem.isVegetarian()) { return true; } } } return false; } }
测试驱动代码
import java.util.*; public class MenuTestDrive { public static void main(String args[]) { // Menu pancakeHouseMenu = new PancakeHouseMenu(); Menu dinerMenu = new DinerMenu(); Menu cafeMenu = new CafeMenu(); Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu); // 各种遍历菜单的方式 waitress.printMenu(); waitress.printVegetarianMenu(); System.out.println("\nCustomer asks, is the Hotdog vegetarian?"); System.out.print("Waitress says: "); if (waitress.isItemVegetarian("Hotdog")) { System.out.println("Yes"); } else { System.out.println("No"); } System.out.println("\nCustomer asks, are the Waffles vegetarian?"); System.out.print("Waitress says: "); if (waitress.isItemVegetarian("Waffles")) { System.out.println("Yes"); } else { System.out.println("No"); } } }
从上面的代码可以看出,迭代器让客户遍历集合的代码更加通用,它不用关心集合内部的存储细节,因为集合对象创建的迭代器封装了遍历具体数据结构的细节。
本章金句
Java Collection框架里面很多类都实现了Iterator接口,可细研究集合类把遍历集合内元素的责任封装在Iterator接口,集合只需要专注在管理集合的元素,比如,添加,删除,查找等。让一个类只做一件事,遵守单一责任原则,这样的设计更加容易维护
相关文章推荐
- 《ERP从内部集成起步》读书笔记——第9章 实施ERP容易忽视和误解的几个问题 9.3上线就是成功吗?
- 《深入理解计算机系统 2nd》部分读书笔记---第9章 虚拟存储器(未完成)
- HeadFirst设计模式_读书笔记_002_观察者模式
- 《从0到1》读书笔记第9章“基础决定命运”第1记: 三权主义
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 《构建之法》读书笔记——第9章 项目经理
- 《Android开发艺术探索》读书笔记 (9) 第9章 四大组件的工作过程
- 读书笔记:《HeadFirst设计模式》
- HeadFirst设计模式_读书笔记_003_装饰者模式
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 《算法导论》读书笔记之第9章 中位数和顺序统计学 最坏情况是线性时间的选择算法
- 《数据结构与算法-Python语言描述》读书笔记(9)第9章排序(关键词:数据结构/算法/Python/排序)
- 《浪潮之巅》读书笔记——第9章 雅虎
- 《C++ Primer 4th》读书笔记 第9章-顺序容器
- Python核心编程---读书笔记:第9章 文件和输入输出
- HeadFirst设计模式_读书笔记_004_单例模式
- 《Android源码设计模式》读书笔记 (14) 第14章 迭代器模式