迭代器模式提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。


类图

设计模式——迭代器模式(Iterator Pattern)_迭代器模式

我们现在使用java.util提供的ArrayList迭代器,所有不需要PancakeHoseMenuIterator这个类了。


(图片源于网络)


代码实现(Java)

// Menu.java
public interface Menu {
    public Iterator createIterator();
}


// PancakeHouseMenu.java
public class PancakeHouseMenu implements Menu {
    ArrayList menuItems;
                            
    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
}


// DinerMenu.java
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 createIterator() {
        return new DinerMenuIterator(menuItems);
        //return new AlternatingDinerMenuIterator(menuItems);
    }
                          
    // other menu methods here
}


// MenuItem.java
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;
    }
}


// Waitress.java
public class Waitress {
    Menu pancakeHouseMenu;
    Menu dinerMenu;
                     
    public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
        this.pancakeHouseMenu = pancakeHouseMenu;
        this.dinerMenu = dinerMenu;
    }
                     
    public void printMenu() {
        Iterator pancakeIterator = pancakeHouseMenu.createIterator();
        Iterator dinerIterator = dinerMenu.createIterator();
        System.out.println("MENU\n----\nBREAKFAST");
        printMenu(pancakeIterator);
        System.out.println("\nLUNCH");
        printMenu(dinerIterator);
    }
                     
    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----\nBREAKFAST");
        printVegetarianMenu(pancakeHouseMenu.createIterator());
        System.out.println("\nLUNCH");
        printVegetarianMenu(dinerMenu.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;
        }
        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.println("\t\t" + menuItem.getPrice());
                System.out.println("\t" + 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;
    }
}


// DinerMenuIterator.java
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;
        }
    }
}


测试代码

// MenuTestDrive.java
public class MenuTestDrive {
    public static void main(String args[]) {
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
        DinerMenu dinerMenu = new DinerMenu();
        Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
        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");
        }
    }
}


运行效果

MENU

----

BREAKFAST

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


LUNCH

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


VEGETARIAN MENU

----

BREAKFAST

K&B's Pancake Breakfast2.99

Pancakes with scrambled eggs, and toast

Blueberry Pancakes3.49

Pancakes made with fresh blueberries, and blueberry syrup

Waffles3.59

Waffles, with your choice of blueberries or strawberries


LUNCH

Vegetarian BLT2.99

(Fakin') Bacon with lettuce & tomato on whole wheat

Steamed Veggies and Brown Rice3.99

Steamed vegetables over brown rice

Pasta3.89

Spaghetti with Marinara Sauce, and a slice of sourdough bread


Customer asks, is the Hotdog vegetarian?

Waitress says: No


Customer asks, are the Waffles vegetarian?

Waitress says: Yes