introduce
Intent : To provide a way to sequentially access the elements of an aggregate object without exposing the object's internal representation.
The main solution : different ways to traverse the entire integration object.
When to use : Iterates over an aggregate object.
How to fix it: Give iterators the responsibility of walking between elements, not aggregate objects.
Key code : Define the interface: hasNext, next.
Application example : iterator in JAVA.
accomplish
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;
}
public String toString() {
return (name + ", $" + price + "\n " + description);
}
}
public interface Menu {
public Iterator<?> createIterator();
}
public class PancakeHouseMenu implements Menu {
ArrayList<MenuItem> menuItems;
public PancakeHouseMenu() {
menuItems = new ArrayList<MenuItem>();
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<MenuItem> getMenuItems() {
return menuItems;
}
//返回JDK自带的迭代器
public Iterator<MenuItem> createIterator() {
return menuItems.iterator();
}
// other menu methods here
}
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",
"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<MenuItem> createIterator() {
return new DinerMenuIterator(menuItems);
//return new AlternatingDinerMenuIterator(menuItems);
}
// other menu methods here
}
Implementation of an iterator
//JDK的迭代器接口
import java.util.Iterator;
public class DinerMenuIterator implements Iterator<MenuItem> {
MenuItem[] list;
int position = 0;
public DinerMenuIterator(MenuItem[] list) {
this.list = list;
}
public MenuItem 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;
}
}
}
public class Waitress {
ArrayList<Menu> menus;
public Waitress(ArrayList<Menu> menus) {
this.menus = menus;
}
//迭代器的使用
public void printMenu() {
Iterator<?> menuIterator = menus.iterator();
while(menuIterator.hasNext()) {
Menu menu = (Menu)menuIterator.next();
printMenu(menu.createIterator());
}
}
//迭代器的使用
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());
}
}
}
run class
public class MenuTestDrive {
public static void main(String args[]) {
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DinerMenu dinerMenu = new DinerMenu();
ArrayList<Menu> menus = new ArrayList<Menu>();
menus.add(pancakeHouseMenu);
menus.add(dinerMenu);
Waitress waitress = new Waitress(menus);
waitress.printMenu();
}
}
operation result
K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries, and blueberry syrup
Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries
Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on whole wheat
BLT, 2.99 -- Bacon with lettuce & tomato on whole wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread
JDK 5 for in 语法
for(Object obj : list){
}
改善使用迭代器的用法
References and citations
1. "Head First Design Patterns" Eric Freeman et al