《HeadFirst设计模式》读书笔记-第9章-迭代器模式

来源:互联网 发布:淘宝情趣珍珠内裤评论 编辑:程序博客网 时间:2024/06/11 15:16

定义

迭代器模式(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");        }    }}

从上面的代码可以看出,迭代器让客户遍历集合的代码更加通用,它不用关心集合内部的存储细节,因为集合对象创建的迭代器封装了遍历具体数据结构的细节。

本章金句

  1. Java Collection框架里面很多类都实现了Iterator接口,可细研究

  2. 集合类把遍历集合内元素的责任封装在Iterator接口,集合只需要专注在管理集合的元素,比如,添加,删除,查找等。让一个类只做一件事,遵守单一责任原则,这样的设计更加容易维护

1 0
原创粉丝点击