设计模式 -- 迭代器模式(Iterator)

---------------------------------------------------------------------

1、场景问题

  考虑这样一个问题: 9个学生对象分别通过数组存储5个和List存储4个来进行记录,如何以一种统一的方式来对它们进行访问。把这个问题抽象一下就是: 如何能够以一个统一的方式来访问内部实现不同的聚合对象。(所谓聚合是指一组对象的组合结构,比如:Java中的集合、数组等)

通过代码进行简单的示例:

  1 /**
  2  * 学生描述模型对象
  3  */
  4 public class Student {
  5 
  6     private int stuId;    //学生编号
  7     private String name; //学生姓名
  8     private int age; //学生年龄
  9     
 10     public int getStuId() {
 11         return stuId;
 12     }
 13     public void setStuId(int stuId) {
 14         this.stuId = stuId;
 15     }
 16     public String getName() {
 17         return name;
 18     }
 19     public void setName(String name) {
 20         this.name = name;
 21     }
 22     public int getAge() {
 23         return age;
 24     }
 25     public void setAge(int age) {
 26         this.age = age;
 27     }
 28     @Override
 29     public String toString() {
 30         return "Student [stuId=" + stuId + ", name=" + name + ", age=" + age
 31                 + "]";
 32     }
 33 }
 34 
 35 /**
 36  * 通过数组来存储学生对象
 37  */
 38 public class ArrayStoreStudent {
 39     //用数组来管理
 40     private Student[] stus = null;
 41     
 42     /**
 43      * 获取学生列表
 44      * @return
 45      */
 46     public Student[] getStus(){
 47         return stus;
 48     }
 49     
 50     /**
 51      * 初始化数据
 52      */
 53     public void initData(){
 54         Student stu1 = new Student();
 55         stu1.setStuId(1);
 56         stu1.setName("学生1");
 57         stu1.setAge(11);
 58         
 59         Student stu2 = new Student();
 60         stu2.setStuId(2);
 61         stu2.setName("学生2");
 62         stu2.setAge(12);
 63         
 64         Student stu3 = new Student();
 65         stu3.setStuId(3);
 66         stu3.setName("学生3");
 67         stu3.setAge(13);
 68         
 69         Student stu4 = new Student();
 70         stu4.setStuId(4);
 71         stu4.setName("学生4");
 72         stu4.setAge(14);
 73         
 74         Student stu5 = new Student();
 75         stu5.setStuId(5);
 76         stu5.setName("学生5");
 77         stu5.setAge(15);
 78         
 79         stus = new Student[5];
 80         stus[0] = stu1;
 81         stus[1] = stu2;
 82         stus[2] = stu3;
 83         stus[3] = stu4;
 84         stus[4] = stu5;
 85     }
 86 }
 87 
 88 import java.util.ArrayList;
 89 import java.util.List;
 90 
 91 /**
 92  * 通过List来存储学生对象
 93  */
 94 public class ListStoreStudent {
 95 
 96     /**
 97      * 聚合对象,这里是Java的集合对象
 98      */
 99     private List<Student> list = new ArrayList<Student>();
100     
101     /**
102      * 获取学生列表
103      * @return
104      */
105     public List<Student> getStuList(){
106         return list;
107     }
108     
109     /**
110      * 初始化数据
111      */
112     public void initData(){
113         Student stu6 = new Student();
114         stu6.setStuId(6);
115         stu6.setName("学生6");
116         stu6.setAge(16);
117         
118         Student stu7 = new Student();
119         stu7.setStuId(7);
120         stu7.setName("学生7");
121         stu7.setAge(17);
122         
123         Student stu8 = new Student();
124         stu8.setStuId(8);
125         stu8.setName("学生8");
126         stu8.setAge(18);
127         
128         Student stu9 = new Student();
129         stu9.setStuId(9);
130         stu9.setName("学生9");
131         stu9.setAge(19);
132         
133         list.add(stu6);
134         list.add(stu7);
135         list.add(stu8);
136         list.add(stu9);
137     }
138 }
139 
140 import java.util.Collection;
141 import java.util.Iterator;
142 
143 public class Client {
144     public static void main(String[] args) {
145         //访问数组存储的学生列表
146         ArrayStoreStudent arrayStoreStudent = new ArrayStoreStudent();
147         //先初始化数据
148         arrayStoreStudent.initData();
149         Student[] stus = arrayStoreStudent.getStus();
150         System.out.println("数组存储的学生列表:");
151         for(int i = 0;i < stus.length;i++){
152             System.out.println(stus[i]);
153         }
154         
155         //访问List存储的学生列表
156         ListStoreStudent listStoreStudent = new ListStoreStudent();
157         //先初始化数据
158         listStoreStudent.initData();
159         Collection stuList = listStoreStudent.getStuList();
160         Iterator it = stuList.iterator();
161         System.out.println("List存储的学生列表:");
162         while(it.hasNext()){
163             Student stu = (Student)it.next();
164             System.out.println(stu);
165         }
166     }
167 }
View Code

---------------------------------------------------------------------

2、解决方案

2.1、使用迭代器模式来解决问题

  迭代器模式的定义: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。(所谓聚合是指一组对象的组合结构,比如:Java中的集合、数组等)

2.2、使用迭代器模式来解决问题的思路

  要以一个统一的方式来访问内部实现不同的聚合对象,首先需要把这个统一的访问方式定义出来 ---> Iterator接口。

  迭代器迭代的是具体的聚合对象,那么不同的聚合对象就应该有不同的迭代器,为了让迭代器以一个统一的方式来操作聚合对象,因此给所有的聚合对象抽象出一个公共的父类--->Aggregate,让它提供操作聚合对象的公共接口。

2.3、迭代器模式的结构和说明

(1) Iterator : 迭代器接口。定义访问和遍历元素的接口。

(2) ConcreteIterator : 具体的迭代器实现对象。实现对聚合对象的遍历,并跟踪遍历时的当前位置。

(3) Aggregate : 聚合对象。定义创建相应迭代器对象的接口。

(4) ConcreteAggregate : 具体聚合对象。实现创建相应的迭代器对象。

2.4、迭代器模式的示例代码

  1 /**
  2  * 迭代器接口,定义访问和遍历元素的操作
  3  */
  4 public interface Iterator {
  5     /**
  6      * 移动到聚合对象的第一个位置
  7      */
  8     public void first();
  9     
 10     /**
 11      * 移到到聚合对象的下一个位置
 12      */
 13     public void next();
 14     
 15     /**
 16      * 判断是否已经移动到聚合对象的最后一个位置
 17      * @return true表示已经移动到聚合对象的最后一个位置
 18      *            false表示还没有移动到聚合对象的最后一个位置
 19      */
 20     public boolean isDone();
 21     
 22     /**
 23      * 获取迭代的当前元素
 24      * @return 迭代的当前元素
 25      */
 26     public Object currentItem();
 27 }
 28 
 29 /**
 30  * 具体的迭代器实现对象,示意的是聚合对象为数组的迭代器
 31  * (不同的聚合对象相应的迭代器实现是不一样的)
 32  */
 33 public class ConcreteIterator implements Iterator {
 34 
 35     /**
 36      * 持有被迭代的具体的聚合对象
 37      */
 38     private ConcreteAggregate aggregate;
 39     
 40     /**
 41      * 内部索引,记录当前迭代到的索引位置
 42      * -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
 43      */
 44     private int index = -1;
 45     
 46     /**
 47      * 构造方法,传入被迭代的具体的聚合对象
 48      * @param aggregate 被迭代的具体的聚合对象
 49      */
 50     public ConcreteIterator(ConcreteAggregate aggregate) {
 51         this.aggregate = aggregate;
 52     }
 53 
 54     @Override
 55     public void first() {
 56         index = 0;
 57     }
 58 
 59     @Override
 60     public void next() {
 61         if(index < this.aggregate.size()){
 62             index = index + 1;
 63         }
 64     }
 65 
 66     @Override
 67     public boolean isDone() {
 68         if(index == this.aggregate.size()){
 69             return true;
 70         }
 71         return false;
 72     }
 73 
 74     @Override
 75     public Object currentItem() {
 76         return this.aggregate.get(index);
 77     }
 78 }
 79 
 80 /**
 81  * 聚合对象的接口,定义创建相应迭代器对象的接口
 82  * @author Administrator
 83  *
 84  */
 85 public abstract class Aggregate {
 86 
 87     /**
 88      * 工厂方法,创建相应迭代器对象的接口
 89      * @return 相应迭代器对象的接口
 90      */
 91     public abstract Iterator createIterator();
 92 }
 93 
 94 /**
 95  * 具体的聚合对象,实现创建相应迭代器对象的功能
 96  * @author Administrator
 97  *
 98  */
 99 public class ConcreteAggregate extends Aggregate {
100     /**
101      * 表示聚合对象具体的内容
102      */
103     private String[] ss = null;
104     
105     /**
106      * 构成方法,传入聚合对象具体的内容
107      * @param ss 聚合对象具体的内容
108      */
109     public ConcreteAggregate(String[] ss) {
110         this.ss = ss;
111     }
112 
113     @Override
114     public Iterator createIterator() {
115         return new ConcreteIterator(this);
116     }
117     
118     /**
119      * 获取索引对应的元素
120      * @param index 索引
121      * @return 索引对应的元素
122      */
123     public Object get(int index){
124         Object retObj = null;
125         if(index < ss.length){
126             retObj = ss[index];
127         }
128         return retObj;
129     }
130     
131     /**
132      * 获取聚合对象的大小
133      * @return 聚合对象的大小
134      */
135     public int size(){
136         return this.ss.length;
137     }
138 }
139 
140 public class Client {
141 
142     public void someOperation(){
143         String[] names = {"张三","李四","王五"};
144         
145         //创建聚合对象
146         Aggregate aggregate = new ConcreteAggregate(names);
147         
148         //循环输出聚合对象中的值
149         Iterator it = aggregate.createIterator();
150         //首先设置迭代器到第一个元素
151         it.first();
152         while(!it.isDone()){
153             //取出当前的元素来
154             Object obj = it.currentItem();
155             System.out.println("the obj == " + obj);
156             //如果还没有迭代到最后,那么就向下迭代一个
157             it.next();
158         }
159     }
160     
161     public static void main(String[] args) {
162         Client client = new Client();
163         client.someOperation();
164     }
165 }
166 
167 运行结果:
168 the obj == 张三
169 the obj == 李四
170 the obj == 王五
View Code

---------------------------------------------------------------------

3、使用迭代器模式来解决场景问题

要使用迭代器模式来解决场景问题,那就需要先定义出抽象的聚合对象和迭代器接口,然后再提供相应的实现。

  1 (1)为了让客户端能够以一个统一的方式进行访问,需要为它们定义一个统一的接口,通过统一的接口来访问:
  2 
  3 /**
  4  * 迭代器接口,定义访问和遍历元素的操作
  5  */
  6 public interface MyIterator {
  7     /**
  8      * 移动到聚合对象的第一个位置
  9      */
 10     public void first();
 11     
 12     /**
 13      * 移动到聚合对象的下一个位置
 14      */
 15     public void next();
 16     
 17     /**
 18      * 判断是否已经移动到聚合对象的最后一个位置
 19      * @return true表示已经移动到聚合对象的最后一个位置
 20      *            false表示还没有移动到聚合对象的最后一个位置
 21      */
 22     public boolean isDone();
 23     
 24     /**
 25      * 获取迭代的当前元素
 26      * @return 迭代的当前元素
 27      */
 28     public Object currentItem();
 29 }
 30 
 31 (2)定义好了统一的接口,下面分别提供对List和数组的实现
 32 /**
 33  *  用来实现访问数组的迭代接口
 34  */
 35 public class ArrayIteratorImpl implements MyIterator {
 36     
 37     /**
 38      * 用来存放被迭代的聚合对象
 39      */
 40     private ArrayStoreStudent aggregate = null;
 41     
 42     /**
 43      * 用来记录当前迭代到的位置的所有
 44      * -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
 45      */
 46     private int index = -1;
 47     
 48     public ArrayIteratorImpl(ArrayStoreStudent aggregate) {
 49         this.aggregate = aggregate;
 50     }
 51 
 52     @Override
 53     public void first() {
 54         index = 0;
 55     }
 56 
 57     @Override
 58     public void next() {
 59         if(index < this.aggregate.size()){
 60             index = index + 1;
 61         }
 62     }
 63 
 64     @Override
 65     public boolean isDone() {
 66         if(index == this.aggregate.size()){
 67             return true;
 68         }
 69         return false;
 70     }
 71 
 72     @Override
 73     public Object currentItem() {
 74         return this.aggregate.get(index);
 75     }
 76 }
 77 
 78 /**
 79  * 用来实现访问List集合的迭代接口,为了外部统一访问方式
 80  */
 81 public class ListIteratorImpl implements MyIterator {
 82 
 83     /**
 84      * 用来存放被迭代的聚合对象
 85      */
 86     private ListStoreStudent aggregate = null;
 87     
 88     /**
 89      * 用来记录当前迭代到的位置索引
 90      * -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
 91      */
 92     private int index = -1;
 93     
 94     public ListIteratorImpl(ListStoreStudent aggregate) {
 95         this.aggregate = aggregate;
 96     }
 97 
 98     @Override
 99     public void first() {
100         index = 0;
101     }
102 
103     @Override
104     public void next() {
105         if(index < this.aggregate.size()){
106             index = index + 1;
107         }
108     }
109 
110     @Override
111     public boolean isDone() {
112         if(index == this.aggregate.size()){
113             return true;
114         }
115         return false;
116     }
117 
118     @Override
119     public Object currentItem() {
120         return this.aggregate.get(index);
121     }
122 }
123 (3)学生模型对象
124 /**
125  * 学生描述模型对象
126  */
127 public class Student {
128 
129     private int stuId;    //学生编号
130     private String name; //学生姓名
131     private int age; //学生年龄
132     
133     public int getStuId() {
134         return stuId;
135     }
136     public void setStuId(int stuId) {
137         this.stuId = stuId;
138     }
139     public String getName() {
140         return name;
141     }
142     public void setName(String name) {
143         this.name = name;
144     }
145     public int getAge() {
146         return age;
147     }
148     public void setAge(int age) {
149         this.age = age;
150     }
151     @Override
152     public String toString() {
153         return "Student [stuId=" + stuId + ", name=" + name + ", age=" + age
154                 + "]";
155     }
156 }
157 (4)聚合对象统一接口
158 /**
159  * 聚合对象的接口,定义创建相应迭代器对象的接口
160  */
161 public abstract class Aggregage {
162     /**
163      * 工厂方法,创建相应迭代器对象的接口
164      * @return 相应迭代器对象的接口
165      */
166     public abstract MyIterator createMyIterator();
167 }
168 (5)聚合对象ArrayStoreStudent和ListStoreStudent 
169 public class ArrayStoreStudent extends Aggregage {
170     /**
171      * 用数组来管理
172      */
173     private Student[] stus;
174     
175     public ArrayStoreStudent() {
176     }
177 
178     
179     @Override
180     public MyIterator createMyIterator() {
181         return new ArrayIteratorImpl(this);
182     }
183 
184     /**
185      * 获取学生列表
186      * @return 学生列表
187      */
188     public Student[] getStus() {
189         return stus;
190     }
191     
192     public Object get(int index){
193         Object retObj = null;
194         if(index < this.stus.length){
195             retObj = stus[index];
196         }
197         return retObj;
198     }
199     
200     public int size(){
201         return this.stus.length;
202     }
203     
204     /**
205      * 初始化数据
206      */
207     public void initData(){
208         Student stu1 = new Student();
209         stu1.setStuId(1);
210         stu1.setName("学生1");
211         stu1.setAge(11);
212         
213         Student stu2 = new Student();
214         stu2.setStuId(2);
215         stu2.setName("学生2");
216         stu2.setAge(12);
217         
218         Student stu3 = new Student();
219         stu3.setStuId(3);
220         stu3.setName("学生3");
221         stu3.setAge(13);
222         
223         Student stu4 = new Student();
224         stu4.setStuId(4);
225         stu4.setName("学生4");
226         stu4.setAge(14);
227         
228         Student stu5 = new Student();
229         stu5.setStuId(5);
230         stu5.setName("学生5");
231         stu5.setAge(15);
232         
233         stus = new Student[5];
234         stus[0] = stu1;
235         stus[1] = stu2;
236         stus[2] = stu3;
237         stus[3] = stu4;
238         stus[4] = stu5;
239     }
240 }
241 
242 import java.util.ArrayList;
243 import java.util.List;
244 
245 public class ListStoreStudent extends Aggregage {
246 
247     private List<Student> list = new ArrayList<Student>();
248     
249     public ListStoreStudent() {
250     }
251 
252     @Override
253     public MyIterator createMyIterator() {
254         return new ListIteratorImpl(this);
255     }
256 
257     /**
258      * 获取学生列表
259      * @return 学生列表
260      */
261     public List<Student> getStusList() {
262         return list;
263     }
264 
265     public Object get(int index){
266         Object retObj = null;
267         if(index < this.list.size()){
268             retObj = this.list.get(index);
269         }
270         return retObj;
271     }
272         
273     public int size(){
274         return this.list.size();
275     }
276         
277     /**
278      * 初始化数据
279      */
280     public void initData(){
281         Student stu6 = new Student();
282         stu6.setStuId(6);
283         stu6.setName("学生6");
284         stu6.setAge(16);
285         
286         Student stu7 = new Student();
287         stu7.setStuId(7);
288         stu7.setName("学生7");
289         stu7.setAge(17);
290         
291         Student stu8 = new Student();
292         stu8.setStuId(8);
293         stu8.setName("学生8");
294         stu8.setAge(18);
295         
296         Student stu9 = new Student();
297         stu9.setStuId(9);
298         stu9.setName("学生9");
299         stu9.setAge(19);
300         
301         list.add(stu6);
302         list.add(stu7);
303         list.add(stu8);
304         list.add(stu9);
305     }
306 }
307 
308 (5)测试类
309 public class Client {
310 
311     public static void main(String[] args) {
312         //访问数组存储的学生列表:
313         ArrayStoreStudent arrayStoreStudent = new ArrayStoreStudent();
314         //先初始化数据
315         arrayStoreStudent.initData();
316         System.out.println("数组存储的学生列表:");
317         printInfo(arrayStoreStudent.createMyIterator());
318         
319         //访问List存储的学生列表:
320         ListStoreStudent listStoreStudent = new ListStoreStudent();
321         //初始化数据
322         listStoreStudent.initData();
323         System.out.println("List存储的学生列表:");
324         printInfo(listStoreStudent.createMyIterator());
325     }
326     
327     public static void printInfo(MyIterator it){
328         //循环输出聚合对象中的值
329         //首先设置迭代器到第一个元素
330         it.first();
331         while(!it.isDone()){
332             //取出当前的元素来
333             Object obj = it.currentItem();
334             System.out.println("the obj == " + obj);
335             //如果还没有迭代到最后,那么就向下迭代一个
336             it.next();
337         }
338     }
339 }
340 
341 运行结果:
342 数组存储的学生列表:
343 the obj == Student [stuId=1, name=学生1, age=11]
344 the obj == Student [stuId=2, name=学生2, age=12]
345 the obj == Student [stuId=3, name=学生3, age=13]
346 the obj == Student [stuId=4, name=学生4, age=14]
347 the obj == Student [stuId=5, name=学生5, age=15]
348 List存储的学生列表:
349 the obj == Student [stuId=6, name=学生6, age=16]
350 the obj == Student [stuId=7, name=学生7, age=17]
351 the obj == Student [stuId=8, name=学生8, age=18]
352 the obj == Student [stuId=9, name=学生9, age=19]
View Code

---------------------------------------------------------------------

4、模式讲解

4.1、迭代器模式的功能

  迭代器模式的功能主要在于提供对聚合对象的迭代访问。围绕"访问"延伸出很多的功能来,比如:

  1. 以不同的方式遍历聚合对象,比如向前、向后等
  2. 对同一个聚合同时进行多个遍历
  3. 以不同的遍历策略来遍历聚合,比如是否需要过滤等
  4. 多态迭代,含义是: 为不同的聚合结构提供统一的迭代接口,也就是说通过一个迭代接口可以访问不同的聚合结构,这就叫做多态迭代。

4.2、迭代器模式的关键思想

  迭代器模式的关键思想是把对聚合对象的遍历和访问从聚合对象中分离出来,放入单独的迭代器中,这样聚合对象会变得简单一些;而且迭代器和聚合对象可以独立地变化和发展,会大大加强系统的灵活性。

4.3、 使用Java的迭代器

  在java.util包里面有一个Iterator接口,在Java中实现迭代器模式是非常简单的,而且Java的集合框架中对聚合对象基本上都提供了迭代器的。

下面就通过使用Java中的迭代器来实现场景问题:

  1 (1)Student类
  2 /**
  3  * 学生描述模型对象
  4  */
  5 public class Student {
  6 
  7     private int stuId;    //学生编号
  8     private String name; //学生姓名
  9     private int age; //学生年龄
 10     
 11     public int getStuId() {
 12         return stuId;
 13     }
 14     public void setStuId(int stuId) {
 15         this.stuId = stuId;
 16     }
 17     public String getName() {
 18         return name;
 19     }
 20     public void setName(String name) {
 21         this.name = name;
 22     }
 23     public int getAge() {
 24         return age;
 25     }
 26     public void setAge(int age) {
 27         this.age = age;
 28     }
 29     @Override
 30     public String toString() {
 31         return "Student [stuId=" + stuId + ", name=" + name + ", age=" + age
 32                 + "]";
 33     }
 34 }
 35 
 36 (2)抽象的Aggregate类
 37 import java.util.Iterator;
 38 
 39 /**
 40  * 聚合对象的接口,定义创建相应迭代器对象的接口
 41  */
 42 public abstract class Aggregate {
 43 
 44     /**
 45      * 工厂方法,创建相应迭代器对象的接口
 46      * @return 相应迭代器对象的接口
 47      */
 48     public abstract Iterator createIterator();
 49 }
 50 
 51 (3)ArrayIteratorImpl类
 52 import java.util.Iterator;
 53 public class ArrayIteratorImpl implements Iterator {
 54 
 55     /**
 56      * 用来存放被迭代的聚合对象
 57      */
 58     private ArrayStoreStudent aggregate = null;
 59     
 60     /**
 61      * 用来记录当前迭代到的位置的索引
 62      */
 63     private int index = 0;
 64     
 65     public ArrayIteratorImpl(ArrayStoreStudent aggregate) {
 66         this.aggregate = aggregate;
 67     }
 68 
 69     @Override
 70     public boolean hasNext() {
 71         //判断是否还有下一个元素
 72         if(aggregate != null && index < aggregate.size()){
 73             return true;
 74         }
 75         return false;
 76     }
 77 
 78     @Override
 79     public Object next() {
 80         Object retObj = null;
 81         if(hasNext()){
 82             retObj = aggregate.get(index);
 83             //每取走一个值,就把已访问索引加1
 84             index++;
 85         }
 86         return retObj;
 87     }
 88 
 89     @Override
 90     public void remove() {
 91         //暂时可以不实现
 92     }
 93 }
 94 
 95 (4)ArrayStoreStudent类
 96 import java.util.Iterator;
 97 
 98 public class ArrayStoreStudent extends Aggregate {
 99 
100     /**
101      * 用数组来管理
102      */
103     private Student[] stus;
104     
105     public ArrayStoreStudent() {
106     }
107 
108     @Override
109     public Iterator createIterator() {
110         return new ArrayIteratorImpl(this);
111     }
112     
113     /**
114      * 获取学生列表
115      * @return 学生列表
116      */
117     public Student[] getStus() {
118         return stus;
119     }
120     
121     public Object get(int index){
122         Object retObj = null;
123         if(index < this.stus.length){
124             retObj = stus[index];
125         }
126         return retObj;
127     }
128     
129     public int size(){
130         return this.stus.length;
131     }
132     
133     /**
134      * 初始化数据
135      */
136     public void initData(){
137         Student stu1 = new Student();
138         stu1.setStuId(1);
139         stu1.setName("学生1");
140         stu1.setAge(11);
141         
142         Student stu2 = new Student();
143         stu2.setStuId(2);
144         stu2.setName("学生2");
145         stu2.setAge(12);
146         
147         Student stu3 = new Student();
148         stu3.setStuId(3);
149         stu3.setName("学生3");
150         stu3.setAge(13);
151         
152         Student stu4 = new Student();
153         stu4.setStuId(4);
154         stu4.setName("学生4");
155         stu4.setAge(14);
156         
157         Student stu5 = new Student();
158         stu5.setStuId(5);
159         stu5.setName("学生5");
160         stu5.setAge(15);
161         
162         stus = new Student[5];
163         stus[0] = stu1;
164         stus[1] = stu2;
165         stus[2] = stu3;
166         stus[3] = stu4;
167         stus[4] = stu5;
168     }
169 }
170 
171 (5)ListStoreStudent类
172 import java.util.ArrayList;
173 import java.util.Iterator;
174 import java.util.List;
175 
176 
177 public class ListStoreStudent extends Aggregate {
178 
179     private List<Student> list = new ArrayList<Student>();
180     
181     public ListStoreStudent() {
182     }
183 
184     @Override
185     public Iterator createIterator() {
186         return list.iterator();
187     }
188 
189     /**
190      * 获取学生列表
191      * @return 学生列表
192      */
193     public List<Student> getStusList() {
194         return list;
195     }
196 
197     public Object get(int index){
198         Object retObj = null;
199         if(index < this.list.size()){
200             retObj = this.list.get(index);
201         }
202         return retObj;
203     }
204         
205     public int size(){
206         return this.list.size();
207     }
208         
209     /**
210      * 初始化数据
211      */
212     public void initData(){
213         Student stu6 = new Student();
214         stu6.setStuId(6);
215         stu6.setName("学生6");
216         stu6.setAge(16);
217         
218         Student stu7 = new Student();
219         stu7.setStuId(7);
220         stu7.setName("学生7");
221         stu7.setAge(17);
222         
223         Student stu8 = new Student();
224         stu8.setStuId(8);
225         stu8.setName("学生8");
226         stu8.setAge(18);
227         
228         Student stu9 = new Student();
229         stu9.setStuId(9);
230         stu9.setName("学生9");
231         stu9.setAge(19);
232         
233         list.add(stu6);
234         list.add(stu7);
235         list.add(stu8);
236         list.add(stu9);
237     }
238 }
239 (6)Client类
240 import java.util.Iterator;
241 
242 public class Client {
243 
244     public static void main(String[] args) {
245         //访问数组存储的学生列表:
246         ArrayStoreStudent arrayStoreStudent = new ArrayStoreStudent();
247         //初始化数据
248         arrayStoreStudent.initData();
249         System.out.println("数组存储的学生列表:");
250         printInfo(arrayStoreStudent.createIterator());
251         
252         //访问List存储的学生列表:
253         ListStoreStudent listStoreStudent = new ListStoreStudent();
254         //初始化数据
255         listStoreStudent.initData();
256         System.out.println("List存储的学生列表:");
257         printInfo(listStoreStudent.createIterator());
258     }
259 
260     public static void printInfo(Iterator it) {
261         while (it.hasNext()) {
262             Student pm = (Student) it.next();
263             System.out.println(pm);
264         }
265     }
266 }
267 
268 运行结果:
269 数组存储的学生列表:
270 Student [stuId=1, name=学生1, age=11]
271 Student [stuId=2, name=学生2, age=12]
272 Student [stuId=3, name=学生3, age=13]
273 Student [stuId=4, name=学生4, age=14]
274 Student [stuId=5, name=学生5, age=15]
275 List存储的学生列表:
276 Student [stuId=6, name=学生6, age=16]
277 Student [stuId=7, name=学生7, age=17]
278 Student [stuId=8, name=学生8, age=18]
279 Student [stuId=9, name=学生9, age=19]
View Code

4.4、带迭代策略的迭代器

  由于迭代器模式把聚合对象和访问聚合的机制实现了分离,所以可以在迭代器上实现不同的迭代策略,最为典型的就是实现过滤功能的迭代器。在实现过滤功能的迭代器中,又有两种常见的需要过滤的情况,一种是对数据进行整条过滤,另一种是对数据进行部分过滤。使用带迭代策略的迭代器实现的一个基本思路,就是先把聚合对象的聚合数据获取到,并存储到迭代器中,主要迭代器就可以按照不同的策略来迭代数据了。

(1)带迭代策略的迭代器示例

 1 import java.util.ArrayList;
 2 import java.util.Collection;
 3 import java.util.Iterator;
 4 
 5 /**
 6  * 带过滤功能的迭代器
 7  */
 8 public class ArrayIteratorImpl implements Iterator {
 9 
10     /**
11      * 用来存放被迭代的数组
12      */
13     private Student[] stus;
14     
15     /**
16      * 用来记录当前迭代到的位置的索引
17      */
18     private int index = 0;
19     
20     public ArrayIteratorImpl(ArrayStoreStudent aggregate) {
21         //在这里先对集合对象的数据进行过滤,比如年龄必须在14岁以下
22         Collection<Student> tmepCol = new ArrayList<Student>();
23         for(Student stu : aggregate.getStus()){
24             if(stu.getAge() < 14){
25                 tmepCol.add(stu);
26             }
27         }
28         //然后把符合要求的数据存放到用来迭代的数组中
29         this.stus = new Student[tmepCol.size()];
30         int i = 0;
31         for(Student stu : tmepCol){
32             this.stus[i] = stu;
33             i++;
34         }
35     }
36 
37     @Override
38     public boolean hasNext() {
39         //判断是否还有下一个元素
40         if(stus != null && index <= (stus.length-1)){
41             return true;
42         }
43         return false;
44     }
45 
46     @Override
47     public Object next() {
48         Object retObj = null;
49         if(hasNext()){
50             retObj = stus[index];
51             //每取走一个值,就把已访问索引加1
52             index++;
53         }
54         //可以在这里进行过滤,比如不让查看姓名
55         ((Student)retObj).setName("***");
56         return retObj;
57     }
58 
59     @Override
60     public void remove() {
61         //暂时可以不实现
62     }
63 }
View Code

(2)谁定义遍历算法的问题

  在实现迭代器模式的时候,一个常见的问题就是: 谁来定义遍历算法? 常见的有两个地方可以来定义遍历算法:一个是聚合对象本身另外一个就是迭代器负责遍历算法

  1. 在聚合对象本身定义遍历算法,通常会在遍历过程中,用迭代器来存储当前迭代的状态,这种迭代器被称为游标,因为它仅用来指示当前的位置。
  2. 在迭代器中定义遍历算法,会比在相同的聚合上使用不同的迭代算法容易,同时也易于在不同的聚合上重用相同的算法。但是如果实现遍历算法需要访问聚合对象的私有变量,那么将遍历算法放入迭代器中会破坏聚合对象的封装性。

4.5、迭代器模式的优点

  1. 更好的封装性。
  2. 迭代器模式可以让你访问一个聚合对象的内容,而无须暴露该聚合对象的内部表示,从而提高聚合对象的封装性。 
  3. 可以以不同的遍历方式来遍历一个聚合。
  4. 使用迭代器模式,使得聚合对象的内容和具体的迭代算法分离开。这样就可以通过使用不同的迭代器的实例、不同的遍历方式来遍历一个聚合对象了。
  5. 迭代器简化了聚合的接口。
  6. 有了迭代器的接口,则聚合本身就不需要再定义这些接口了,从而简化了聚合的接口定义。

4.6、 思考迭代器模式

迭代器模式的本质: 控制访问聚合对象中的元素。迭代器能实现:无须暴露聚合对象的内部实现,就能够访问到聚合对象中的各个元素。

---------------------------------------------------------------------

---------------------------------------------------------------------

---------------------------------------------------------------------

---------------------------------------------------------------------

---------------------------------------------------------------------

 

posted @ 2017-02-05 10:29  火爆泡菜  阅读(441)  评论(0编辑  收藏  举报