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

原创 2016年05月30日 23:06:06

迭代器模式(Iterator Pattern)

概念:

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


迭代器模式是一种简单常见的设计模式,在我们使用编程语言中的集合容器都会有迭代器。


组成:

迭代器模式

Aggregate(抽象聚合):共同的接口供所有的聚合使用。

ConcreteAggregate(聚合):持有一个对象的集合,并实现 createIterator 方法,返回集合的迭代器。

Iterator(抽象迭代器接口):包含所有迭代器都必须实现的方法。

ConcreteIterator(具体迭代器):实现了迭代器接口的具体迭代器。


例子:

现有两家超市,一家为水果超市,一家为零食超市。他们分别请了两位编程人员帮他们实现打印品种清单程序。结果第一家编程人员用数组集合来存储不同的水果,第二家编程人员用 ArrayList 集合来存储零食种类。如下:

物品类:

public class Item {
    private String name;
    private String description;
    double price;

    public Item(String name, String description, double price) {
        this.name = name;
        this.description = description;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public double getPrice() {
        return price;
    }
}

水果超市类:

public class FruitSupermarket {
    ArrayList menuItems;

    public FruitSupermarket() {
        menuItems = new ArrayList();
        //添加水果
        addItem("苹果", "红色的", 1.99);
        addItem("香蕉", "黄色的", 2.00);
        addItem("橙子", "横色的", 3.12);
    }

    public void addItem(String name, String description, double price) {
        Item item = new Item(name, description, price);
        menuItems.add(item);
    }

    public ArrayList getMenuItems() {
        return menuItems;
    }
}

零食超市类:

public class SnacksSupermarket {
    static final int MAX_ITEMS = 6;
    int numberOfItems = 0;
    Item[] menuItems;

    public SnacksSupermarket() {
        menuItems = new Item[MAX_ITEMS];
        //添加零食
        addItem("牛奶", "伊利", 2.24);
        addItem("糖", "阿尔卑斯", 5.12);
        addItem("巧克力", "金蒂", 1.23);
    }

    public void addItem(String name, String description, double price) {
        Item item = new Item(name, description, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,清单已满...");
        } else {
            menuItems[numberOfItems] = item;
            numberOfItems += 1;
        }
    }

    public Item[] getMenuItems() {
        return menuItems;
    }
}

现在假设两家超市合并了,我们要遍历两家超市的清单。

public class Supermarket {
    FruitSupermarket fruitSupermarket;
    SnacksSupermarket snacksSupermarket;

    public Supermarket() {
        fruitSupermarket = new FruitSupermarket();
        snacksSupermarket = new SnacksSupermarket();
    }
    //遍历菜单方法,内部分别包含两家超市的遍历。
    public void printMenu() {
        ArrayList fruitItems = fruitSupermarket.getMenuItems();
        Item[] snacksItems = snacksSupermarket.getMenuItems();

        //遍历水果超市
        System.out.println("fruitItem:");
        for (int i = 0; i < fruitItems.size(); ++i) {
            Item item = (Item) fruitItems.get(i);
            System.out.print("name:" + item.getName());
            System.out.print(" description:" + item.getDescription());
            System.out.println(" price:" + item.getPrice());
        }
        //遍历零食超市
        System.out.println("\nsnacksItem:");
        for (int i = 0; i < snacksSupermarket.getNumberOfItems(); ++i) {
            Item item = snacksItems[i];
            System.out.print("name:" + item.getName());
            System.out.print(" description:" + item.getDescription());
            System.out.println(" price:" + item.getPrice());
        }
    }

    public static void main(String[] args) {
        Supermarket supermarket = new Supermarket();
        supermarket.printMenu();
    }
}

迭代器模式


如果将来再次合并超市又必须修改代码,增加一个循环,我们可以发现上述代码成了 面向实现 编程而不是 面向接口
我们来通过 迭代器模式 改进这个类。


先将两个超市类增加 createIterator() 方法,返回内部集合的迭代器。

由于 ArrayList 本身有迭代器,我们直接返回即可。

    //省略原本类的方法
    public Iterator createIterator() {
        return menuItems.iterator();
    }

但零食超市中的数组集合没有迭代器,我们自己实现一个。

//Java 提供了迭代器接口,我们直接实现即可
public class SnacksIterator implements Iterator {
    Item[] menuItems;
    int position = 0;

    public SnacksIterator(Item[] menuItems) {
        this.menuItems = menuItems;
    }
    //判断是否有下一个元素方法
    public boolean hasNext() {
        if (position >= menuItems.length || menuItems[position] == null) {
            return false;
        }else {
            return true;
        }
    }
    //返回下一个对象方法
    public Object next() {
        Item menuitem = menuItems[position];
        position += 1;
        return menuitem;
    }
}
    //...省略原本类和方法
    public Iterator createIterator() {
        return new SnacksIterator(menuItems);
    }

超市类:

public class Supermarket {
    FruitSupermarket fruitSupermarket;
    SnacksSupermarket snacksSupermarket;

    public Supermarket() {
        fruitSupermarket = new FruitSupermarket();
        snacksSupermarket = new SnacksSupermarket();
    }

    //由于实现了统一的接口,再次添加我们继续创建对应的迭代器类,加入 printMenu 即可。
    public void printMenu() {
        //我们也可以将所有的清单加入集合中,这样下面的代码也不用改变了。
        Iterator fruitIterator = fruitSupermarket.createIterator();
        Iterator snacksIterator = snacksSupermarket.createIterator();

        System.out.println("FruitSupermarket");
        printMenu(fruitIterator);
        System.out.println("\nSnacksSupermarket");
        printMenu(snacksIterator);
    }

    private void printMenu(Iterator iterator) {
        while (iterator.hasNext()) {
            Item item = (Item) iterator.next();
            System.out.print("name:" + item.getName());
            System.out.print(" description:" + item.getDescription());
            System.out.println(" price:" + item.getPrice());
        }
    }

    public static void main(String[] args) {
        Supermarket supermarket = new Supermarket();
        supermarket.printMenu();
    }
}

迭代器模式


适用场景:

  • 访问一个聚合对象的内容而无需暴露它的内部表示。
  • 需要为聚合对象提供多种遍历方式。
  • 为遍历不同的聚合结构提供一个统一的接口 (即, 支持多态迭代)

补充:设计原则

单一设计原则:一个类应该只有一个引起变化的原因
我们应该避免类内的改变,因为修改代码很容易造成许多潜在的错误。如果一个类具有两个改变的原因,那么类变化的几率就很大了,并且当它真的改变时,我们的设计中会有两方面受到影响。

当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚。反之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。

版权声明:free, open, share

如何让孩子爱上设计模式 ——16.迭代器模式(Iterator Pattern)

如何让孩子爱上设计模式 ——16.迭代器模式(Iterator Pattern)标签: 设计模式初涉描述性文字本节讲解的是:迭代器模式(Iterator Pattern),说到迭代器,如果你学过Jav...

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

一、引言 在上篇博文中分享了我对命令模式的理解,命令模式主要是把行为进行抽象成命令,使得请求者的行为和接受者的行为形成低耦合。在一章中,将介绍一下迭代器模式。下面废话不多说了,直接进入本博文的主题。...

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

场景一 描述:周五下午,我正在看技术网站,第六感官发觉有人在身后,扭头一看,我C,老大站在背后,赶忙站起来, “王经理,你找我?” 我说。 “哦,在看技术呀。有个事情找你谈一下,你到我办公室来一下。”...

我所理解的设计模式(C++实现)——迭代器模式(Iterator Pattern)

概述:         在现在的电视机中,我们使用[后一个]和[前一个]按钮可以很方便的换台,当按下[后一个]按钮时,将切换到下一个预置的频道。想象一下在陌生的城市中的旅店中看电视。当改变频道时...

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

概述:         在软件开发中,我们经常需要使用聚合对象来存储一系列数据。聚合对象拥有两个职责:一是存储数据;二是遍历数据。从依赖性来看,前者是聚合对象的基本职责;而后者既是可变化的,又是可分离...

您的设计模式——迭代器模式【Iterator Pattern】

周五下午,我正在看技术网站,第六感官发觉有人在身后,扭头一看,我 C,老大站在背后,赶忙站起来, “王经理,你找我?” 我说。“哦,在看技术呀。有个事情找你谈一下,你到我办公室来一下。” 老大说。 ...

我所理解的设计模式(C++实现)——迭代器模式(Iterator Pattern)

关于迭代器模式,在C++下可以参看 STL iterators 的实现;在.NET下实现Iterator模式,对于聚集接口和迭代器接口已经存在了,其中IEnumerator扮演的就是迭代器的角色,而I...
  • LCL_data
  • LCL_data
  • 2013年07月12日 13:19
  • 13910

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

概念 用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。 迭代器模式属于行为型模式。 要素 意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示...

Iterator Pattern--迭代器设计模式

1. What is? 关于迭代器设计模式下面的解释如果看不下去可以看这个链接,以及这个。 设计意图: 1). 提供一种顺序访问一组对象而不用暴露其潜在实现的机制。 2). C++和java标准...

JS-Javascript 迭代器设计模式 Iterator pattern

这篇博文简短的提一下Iterator的设计模式,以及这种设计模式给我们带来什么样的好处。1.begin为了体现面向对象的特性(近年来的ES6为这方面做了很大的努力),此篇博文的语言编写基于typesc...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式 —— 迭代器模式(Iterator Pattern)
举报原因:
原因补充:

(最多只允许输入30个字)