1.1概述
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露对象的内部表示。这就是迭代器模式的定义。
合理组织数据的结构以及相关操作是程序设计的一个重要方面,比如在程序设计中经常会使用诸如链表、散列表等数据结构。链表和散列表等数据结构都是可以存放若干个对象的集合,其区别是按照不同的方式进行存储对象。我们希望无论何种集合,应当允许程序以一种统一的方式遍历集合中的对象,而不需要知道这些对象在集合中是如何表达及存储的。
例如,一栋楼中居住着张三、李四、王五三个人,分别被安排在不同的房间,张三知道李四的房间,李四知道王五的房间。假如有一个警察,他并不知道他们三个是如何居住的,只想找到他们,那么警察可以用一个next()方法找人,该方法的特点是在找到一个人的同时立刻让这个人说出他知道的下一个人的房间,然后警察再调用next()方法找到下一个人。如果警察调用next()方法首先找到张三,就可以依次找到李四和王五,具体如图一所示:
图一:警察找人
迭代器模式是遍历集合的成熟模式,迭代器模式的关键是将遍历集合的任务交给一个称作迭代器的对象。比如,前面所述的楼就是一个集合,其中的人就是集合中的对象,而警察就是一个迭代器。
1.2模式的结构
迭代器模式的结构中包括四种角色:
(1)集合(Aggregate):一个接口,规定了具体集合需实现的操作。
(2)具体集合(ConcreteAggregate):具体集合是实现集合接口的类的实例,具体集合按照一定的结构存储对象。具体集合应当有一个方法,该方法返回一个针对该集合的具体迭代器。
(3)迭代器(Iterator):一个接口,规定了遍历集合的方法,比如next()方法。
(4)具体迭代器(ConcreteIterator):实现迭代器接口的类的实例,具体迭代器在实现迭代器接口所规定的遍历集合的方法时,比如next()方法,要保证next()方法的首次调用即按照集合的数据结构找到该集合中的一个对象,而且每当找到集合中的一个对象,立刻根据该集合的存储结构得到待遍历的后继对象的引用,并保证依次调用next()方法可以遍历集合。
迭代器模式结构的类图如下图二所示:
图二:迭代器模式类图
1.3迭代器模式的优点
(1)用户使用迭代器模式访问集合中的对象,而不需要知道这些对象在集合中是如何表达及存储的。
(2)用户可以同时使用多个迭代器遍历一个集合。
1.4适合使用迭代器模式的情景
(1)让用户访问一个集合中对象,但不想暴露对象在集合中的存储结构。
(2)希望对遍历不同的集合提供一个统一的接口。
1.5迭代器模式的使用
以下通过一个简单的问题讲述迭代器模式中所涉及的各个角色。
用一种集合模拟保险箱,该集合用返回的迭代器模拟点钞机。具体如下:
(1)集合(Aggregate)
在这里使用java.util包中的Collection接口作为模式中的集合角色。Java所有的集合都实现了该接口。
(2)具体集合(ConcreteAggregate)在这里使用java.util包中的HashSet类的实例作为模式中的具体集合角色。
需要注意的是,在JDK1.5之后,要使用泛型,即使用HashSet<E>类(E是一个泛型)来创建一个集合对象。在使用HashSet<E>创建一个集合时,必须指定E的具体类型,即指定集合中存放的对象的具体类型,例如:
HashSet<String> set = new HashSet<String>();
那么,该集合set只可以存放String对象的引用,比如:
Set.add(“OK”);
向集合set中添加元素,该元素中存放者”OK”对象的引用,但是:
Set.add(new java.awt.Button());就是一个非法操作。
(3)迭代器(Iterator)
在本问题中,使用的迭代器是java.util包中的Iterator接口,该接口有:
Boolean hashNext()
Object next()
Void remove()
三个方法。迭代器通过next()方法依次返回集合中的对象,通过调用hashNext()方法判断集合中是否还有对象未被next()方法返回,调用remove()方法从集合中删除最近一次调用next()方法返回的对象。
(4)具体迭代器
HashSet创建的集合可以使用iterator()方法返回一个实现Iterator接口类的实例,即一个具体迭代器。
(5)具体使用
通过EightApllication类来具体实现上述相关类和接口,来实现适配器模式的运用,其代码如下:
package com.liuzhen.eight_iterator;import java.util.*;public class EightApplication { public static void main(String args[]){ int n = 20; int sum = 0; Collectionset = new HashSet (); //集合对象 for(int i = 0;i <= n;i++){ if(i == n/2 || i == n/5 || i == n/6) set.add(new Money(100,false)); else set.add(new Money(100,true)); } Iterator iterator = set.iterator(); //迭代器 System.out.println("保险箱共有"+set.size()+"张人民币"); int k = 0; while(iterator.hasNext()){ Money money = iterator.next(); k++; if(money.getIsTrue() == false){ System.out.println("第"+k+"张是假币,被销毁"); iterator.remove(); k++; } } System.out.println("保险箱现有真人民币"+set.size()+"张,总价值是:"); iterator = set.iterator(); while(iterator.hasNext()){ Money money = iterator.next(); sum = sum+money.getValue(); } System.out.println(sum+"元"); }}
相关类Money.java代码如下:
package com.liuzhen.eight_iterator;public class Money { int value; private boolean isTrue; Money(int value , boolean isTrue){ this.value = value; this.isTrue = isTrue; } public boolean getIsTrue(){ return isTrue; } public int getValue(){ return value; }}
运行结果:
保险箱共有21张人民币第4张是假币,被销毁第10张是假币,被销毁第18张是假币,被销毁保险箱现有真人民币18张,总价值是:1800元
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5