Gof说:提供一种方法顺序访问一个聚合对象中的各元素,而又不暴露该对象的内部表示。
关键思想是将对列表的访问和遍历从列表对象中分离出来,并放入一个迭代器(iterator)对象中。
示例:班级(Classes)是一个聚合对象,里面包含一定数量的学生(Student),获取每个学生的信息。
Aggregate代表聚集体.实现了Aggregate接口的类都属于聚集体.包含一个获取迭代器的iterate的方法.
Iterator迭代器接口,提供执行遍历的功能hasNext与next方法.
Classes为班级类,实现了Aggregate接口所以它是一个聚集体,内部包含了一个Student数组和一个size,可以添加学生和获取班级迭代器进行迭代.
ClassesIterator班级类的迭代器,实现了Iterator接口,提供对班级内的学生进行迭代的功能.包含一个被迭代班级的对象和一个迭代索引位置.
Student学生信息.
代码Aggregate:
/** * 可以被迭代的聚合接口 * * @version 2010-11-24 上午10:35:22 * @author _an. * */ public interface Aggregate { /** * 拿到迭代器 * * @return */ Iterator iterator(); }
代码Iterator:
/** * 迭代器 * * @version 2010-11-24 上午10:41:39 * @author _an. * */ public interface Iterator { /** * 判断是否有下一个元素 * * @return */ boolean hasNext(); /** * 拿到当前元素,并将标识转到下一个元素 * * @return */ Object next(); }
代码Classes:
/** * 容纳人的班级 * * @version 2010-11-24 上午11:13:44 * @author _an. * */ public class Classes implements Aggregate { /** * 容纳学生的数组 */ private Student[] students = null; /** * 当前容纳情况 */ private int size = 0; /** * 构造函数,必须制定班级可容纳多少个学生 * @param capacity 容纳数量 */ public Classes(int capacity) { if(capacity < 1) { throw new RuntimeException("容量必须大于0"); } // 初始化容纳学生的数组 this.students = new Student[capacity]; } @Override public String toString() { return Arrays.toString(students); } /** * 当前容纳学生的数量 * * @return */ public int size() { return this.size; } /** * 获取某个位置上的学生信息 * * @param index 获取位置 * @return 学生信息 */ public Student studentAt(int index) { if (this.students == null || this.size == 0) { throw new RuntimeException("班级内没有学生信息"); } if(this.size <= index) { throw new RuntimeException("获取位置超出了班级当前容纳数量"); } return this.students[index]; } /** * 添加学生信息到班级中 * * @param student 学生信息 */ public void addStudent(Student student) { if (this.size >= this.students.length) { throw new RuntimeException("超出容纳范围"); } // 保存学生信息 this.students[this.size] = student; // 当前容纳数量加1 this.size++; } /** * 获取班级的迭代器 */ @Override public Iterator iterator() { // 构造当前班级的迭代器对象,将自身传入迭代器构造函数 return new ClassesIterator(this); } }
代码ClassesIterator:
/** * 班级迭代器 * * @version 2010-11-24 上午11:23:37 * @author _an. * */ public class ClassesIterator implements Iterator { /** * 班级对象 */ private Classes classes; /** * 当前迭代位置 */ private int index = 0; /** * 构造函数,必须传入被迭代的班级对象 * * @param classes * 被迭代的班级对象 */ public ClassesIterator(Classes classes) { this.classes = classes; } /** * 判断是否可以被继续迭代(判断是否有下一个元素) */ @Override public boolean hasNext() { return index < this.classes.size(); } /** * 执行迭代操作(获取下一个元素) */ @Override public Object next() { //获取到index索引位置的person元素,并让索引指向下一个元素 return this.classes.studentAt(index++); } }
代码Student:
/** * 学生信息 * * @version 2010-11-24 上午11:36:48 * @author _an. * */ public class Student { //姓名 private String name; //年龄 private int age; //性别 private String sex; /** * @param name * @param age * @param sex */ public Student(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("/nname: " + name); builder.append(",age: " + age); builder.append(",sex: " + sex); return builder.toString(); } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setSex(String sex) { this.sex = sex; } public String getSex() { return sex; } }
测试代码IteratorTest:
/** * 迭代器测试 * @version 2010-11-24 上午11:32:08 * @author _an. * */ public class IteratorTest { /** * 测试迭代器 */ @Test public void testIterator(){ // 可以容纳30个人的班级 Classes classes = new Classes(30); // 构造学生的性别 String[] sexs = new String[]{"男","女"}; // 添加学生信息到班级中 for(int i=0; i<22; i++) { double random = Math.random(); classes.addStudent(new Student("学生" + i, (int) (random * 28), sexs[(int)(random*100)%2])); } System.out.println(classes); System.out.println("-------------------------分割线-------------------------"); // 获取迭代对象 Iterator iterator = classes.iterator(); // 迭代 while(iterator.hasNext()){ // 获取迭代到的对象 Student student = (Student)iterator.next(); System.out.println(student); } } }
/** * 容纳人的班级 * * @version 2010-11-24 上午11:13:44 * @author _an. * */ public class Classes implements Aggregate { /** * 容纳学生的集合 */ private Vector
Iterator:
/** * 迭代器 * * @version 2010-11-24 上午10:41:39 * @author _an. * */ public interface Iterator { /** * 获取第一个元素 * * @return */ public Object first(); /** * 判断是否有下一个元素 * * @return */ public boolean hasNext(); /** * 获取下一个元素 * * @return */ public Object next(); /** * 获取最后一个元素 * * @return */ public Object last(); /** * 判断是否有上一个元素 * * @return */ public boolean hasPrev(); /** * 获取上一个元素 * * @return */ public Object prev(); }
ClassesIterator:
/** * 班级迭代器 * * @version 2010-11-24 上午11:23:37 * @author _an. * */ public class ClassesIterator implements Iterator { /** * 班级对象 */ private Classes classes; /** * 当前迭代位置 */ private int index = 0; /** * 构造函数,必须传入被迭代的班级对象 * * @param classes * 被迭代的班级对象 */ public ClassesIterator(Classes classes) { this.classes = classes; } /** * 获取第一个元素 * * @return */ public Object first(){ // 将索引指向最开始 index = 0; return this.next(); } /** * 判断是否可以被继续迭代(判断是否有下一个元素) */ @Override public boolean hasNext() { return index < this.classes.size(); } /** * 执行迭代操作(获取下一个元素) */ @Override public Object next() { //获取到index索引位置的person元素,并让索引指向下一个元素 return this.classes.studentAt(index++); } /** * 获取最后一个元素 * * @return */ public Object last(){ // 将索引指向末尾 index = this.classes.size(); return this.prev(); } /** * 判断是否有上一个元素 * * @return */ @Override public boolean hasPrev() { return index > 0; } /** * 获取上一个元素 * * @return */ @Override public Object prev() { // 获取索引指向的上一个元素 return this.classes.studentAt(--index); } }
IteratorTest:
/** * 迭代器测试 * * @version 2010-11-24 上午11:32:08 * @author _an. * */ public class IteratorTest { /** * 测试迭代器 */ @Test public void testIterator() { // 创建班级 Classes classes = new Classes(); // 构造学生的性别 String[] sexs = new String[] { "男", "女" }; // 添加学生信息到班级中 for (int i = 0; i < 22; i++) { double random = Math.random(); classes.addStudent(new Student("学生" + i, (int) (random * 28), sexs[(int)(random*100)%2])); } System.out.println(classes); System.out.println("---------------------分割线---------------------"); // 获取迭代对象 Iterator iterator = classes.iterator(); // 迭代 while (iterator.hasNext()) { // 获取迭代到的对象 Student student = (Student) iterator.next(); System.out.println(student); } System.out.println("---------------------分割线---------------------"); // 倒序迭代 if (!iterator.hasNext()) { while (iterator.hasPrev()) { // 获取迭代到的对象 Student student = (Student) iterator.prev(); System.out.println(student); } } System.out.println("---------------------分割线---------------------"); System.out.println("last: " + iterator.last()); System.out.println("first: " + iterator.first()); } }
为什么要在Iterator Pattern这么麻烦的东西上花时间?以数组概念思考Pattern,用for语句让他循环下去不就得了吗?为什么出了聚合之外,还要特别建立像Iterator这样的参与者?
最大的理由是因为利用Iterator可以跟实现分开,单独进行递增,请看下面的程序代码:
// 迭代 while (iterator.hasNext()) { // 获取迭代到的对象 Student student = (Student) iterator.next(); System.out.println(student); }
这里只用到hasNext和next这两个Iterator的方法。并没有调用Classes实现时所使用的方法。换句话说,这里的while循环不会受到Classes实现的影响。
像上面的例子开始的时候使用数组管理学生,后面换成了vector。无论Classes修改成怎样,Classes仍然还有iterate方法,只要能返回正确的Iterator(即返回正常实现了hasNext,next方法的类的对象实例),上面的while循环即使一字不改也能正常执行。