设计模式-迭代器模式Interator

设计模式-迭代器模式Interator

概念:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。

下面设计一个例子,演示迭代器模式的使用

例如有下面一种情况,一个餐厅,有两个厨师.一个负责早餐,一个负责午餐.但是呢,两个师傅都非常有个性.一个师傅的菜单(BreakfastMenu)是用集合(List进行表示的,而另一个师傅的菜单(LunchMenu)是用数组(MenuItem[]).如果此时,服务员(Waitress)需要向客人展示菜单里的内容就非常的不方便,除非让两个厨师统一.但是之前说过了,师傅太有个性了,就不改.那么下面,使用代码演示一下.
首先,菜品类:
public class MenuItem {
    private String name;
    private double price;
    public MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public double getPrice() {
        return price;
    }
    @Override
    public String toString() {
        return "MenuItem{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

做早餐的师傅,菜单是用集合形式表示的

public class BreakfastMenu {
    private List<MenuItem> menuItems;
    public BreakfastMenu() {
        menuItems = new ArrayList<>();
        addItem("豆浆", 1.0);
        addItem("鸡蛋", 1.0);
        addItem("肉包子", 2.5);
        addItem("豆腐脑", 2.0);
    }
    private void addItem(String name, double price) {
        MenuItem item = new MenuItem(name, price);
        menuItems.add(item);
    }
    public List<MenuItem> getMenuItems() {
        return menuItems;
    }
}

做午餐的师傅,菜单是使用数组表示的

public class LunchMenu {
    private static final int MAX_ITEMS = 3;
    private MenuItem[] menuItems;
    private int index;
    public LunchMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("鸡排饭", 8.0);
        addItem("蛋炒饭", 7.0);
        addItem("白菜盖饭", 9.0);
    }
    private void addItem(String name, double price) {
        MenuItem item = new MenuItem(name, price);
        menuItems[index] = item;
        index++;
    }
    public MenuItem[] getMenuItems() {
        return menuItems;
    }
}

此时,服务员的做法如下:

public class Waitress {
    private BreakfastMenu breakfastMenu;
    private LunchMenu lunchMenu;
    public Waitress(BreakfastMenu breakfastMenu, LunchMenu lunchMenu) {
        this.breakfastMenu = breakfastMenu;
        this.lunchMenu = lunchMenu;
    }
  blic void printMenu(){
        printBreakfastMenu();
        printLunchMenu();
    }
    public void printBreakfastMenu(){
    System.out.println("---早餐---");
        List<MenuItem> breakfast = breakfastMenu.getMenuItems();
        for (int i = 0; i < breakfast.size(); i++) {
            System.out.println(breakfast.get(i));
        }
    }
    public void printLunchMenu(){
        System.out.println("---午餐---");
        MenuItem [] lunch = lunchMenu.getMenuItems();
        for (int i = 0; i < lunch.length; i++) {
            System.out.println(lunch[i]);
        }
    }
}

执行程序如下:

public class Hotel {
    public static void main(String[] args) {
        BreakfastMenu breakfastMenu = new BreakfastMenu();
        LunchMenu lunchMenu = new LunchMenu();
        Waitress waitress = new Waitress(breakfastMenu, lunchMenu);
        waitress.printMenu();
    }
}
可以看到,服务员(Waitress)分别遍历了两种集合,那如果再加个有个性的厨师呢?再来个用Map存储的,是不是还得再写一个遍历?
下面,介绍迭代器(Interator)的用法
首先,创建迭代器接口
public interface Iterator<T> {
    boolean hasNext();
    T next();
}

早餐菜单的实现类如下:

public class BreakfastMenuIterator implements Iterator<MenuItem> {
    private List<MenuItem> items;
    private int index;
    public BreakfastMenuIterator(List<MenuItem> items) {
        this.items = items;
    }
    @Override
    public boolean hasNext() {
        if (index < items.size()) return true;
        return false;
    }
    @Override
    public MenuItem next() {
        return items.get(index++);
    }
}

午餐菜单实现类如下:

public class LunchMenuIterator implements Iterator<MenuItem> {
    private MenuItem [] items;
    private int index;

    public LunchMenuIterator(MenuItem[] items) {
        this.items = items;
    }
    @Override
    public boolean hasNext() {
        if (index < items.length) return true;
        return false;
    }
    @Override
    public MenuItem next() {
        MenuItem item = items[index++];
        return item;
    }
}

然后,分别在BreakfastMenu和LunchMenu类下面公布一个新方法,createInterator()

public class BreakfastMenu {
    /** 其余代码未变,省略 */
    public Iterator createIterator(){
        return new BreakfastMenuIterator(menuItems);
    }
}

同样,LunchMenu

public class LunchMenu {
    /** 其余代码未变,省略 */
    public Iterator createIterator(){
        return new LunchMenuIterator(menuItems);
    }
}

修改Waitree类

public class Waitress {
    private final Iterator breakfastIterator;
    private final Iterator dinerIterator;

    public Waitress(BreakfastMenu breakfastMenu, LunchMenu lunchMenu) {
        breakfastIterator = breakfastMenu.createIterator();
        dinerIterator = lunchMenu.createIterator();
    }
    public void printMenu(){
        printBreakfastMenu();
        printLunchMenu();
    }

    private void print(Iterator iterator){
        while (iterator.hasNext()){
            MenuItem item = (MenuItem) iterator.next();
            System.out.println(item.toString());
        }
    }

    public void printBreakfastMenu(){
        System.out.println("---早餐---");
        print(breakfastIterator);
    }
    public void printLunchMenu(){
        System.out.println("---午餐---");
        print(dinerIterator);
    }
}

执行程序的代码无改动.
可以看到,此时Waitree类完全不用考虑菜单的类型,关心的只是是否实现了迭代器的接口.而其他的菜单类,只是添加了一个方法而已,对厨师来说,那只是小事儿一桩.
上面是咱们自己创建了一个迭代器,实际上在java中,系统有Interator这个接口,并且List/Map等集合类也都是有直接的方法来提供迭代器,例如:

List<MenuItem> breakfastMenus = new ArrayList<>();
        java.util.Iterator listIterator = breakfastMenus.iterator();
        Map<String,MenuItem> map = new HashMap<>();
        java.util.Iterator mapIterator = map.values().iterator();

你可能感兴趣的:(设计模式,迭代器)