---------------------------------------------------------------------
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 }
---------------------------------------------------------------------
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 == 王五
---------------------------------------------------------------------
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]
---------------------------------------------------------------------
4、模式讲解
4.1、迭代器模式的功能
迭代器模式的功能主要在于提供对聚合对象的迭代访问。围绕"访问"延伸出很多的功能来,比如:
- 以不同的方式遍历聚合对象,比如向前、向后等
- 对同一个聚合同时进行多个遍历
- 以不同的遍历策略来遍历聚合,比如是否需要过滤等
- 多态迭代,含义是: 为不同的聚合结构提供统一的迭代接口,也就是说通过一个迭代接口可以访问不同的聚合结构,这就叫做多态迭代。
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]
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 }
(2)谁定义遍历算法的问题
在实现迭代器模式的时候,一个常见的问题就是: 谁来定义遍历算法? 常见的有两个地方可以来定义遍历算法:一个是聚合对象本身,另外一个就是迭代器负责遍历算法。
- 在聚合对象本身定义遍历算法,通常会在遍历过程中,用迭代器来存储当前迭代的状态,这种迭代器被称为游标,因为它仅用来指示当前的位置。
- 在迭代器中定义遍历算法,会比在相同的聚合上使用不同的迭代算法容易,同时也易于在不同的聚合上重用相同的算法。但是如果实现遍历算法需要访问聚合对象的私有变量,那么将遍历算法放入迭代器中会破坏聚合对象的封装性。
4.5、迭代器模式的优点
- 更好的封装性。
- 迭代器模式可以让你访问一个聚合对象的内容,而无须暴露该聚合对象的内部表示,从而提高聚合对象的封装性。
- 可以以不同的遍历方式来遍历一个聚合。
- 使用迭代器模式,使得聚合对象的内容和具体的迭代算法分离开。这样就可以通过使用不同的迭代器的实例、不同的遍历方式来遍历一个聚合对象了。
- 迭代器简化了聚合的接口。
- 有了迭代器的接口,则聚合本身就不需要再定义这些接口了,从而简化了聚合的接口定义。
4.6、 思考迭代器模式
迭代器模式的本质: 控制访问聚合对象中的元素。迭代器能实现:无须暴露聚合对象的内部实现,就能够访问到聚合对象中的各个元素。
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------