迭代器模式: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式
1 概述
比如说,现在我们有两个聚合对象,一个是数组,一个是 ArrayList
, 利用这两个对象分别存储文理科课程信息,像下面这样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class LiberalLessons {
public static final int MAX_LESSONS = 3; private int numberOfLessons = 0; private String[] lessons;
public LiberalLessons() { lessons = new String[MAX_LESSONS]; addLessons("Political"); addLessons("Geography"); addLessons("History"); }
private void addLessons(String lesson) { lessons[numberOfLessons] = lesson; numberOfLessons++; }
public String[] getLessons() { return lessons; } }
public class ScienceLessons { private ArrayList<String> lessons;
public ScienceLessons() { lessons = new ArrayList<>(); addLessons("Physical"); addLessons("Chemical"); addLessons("Biological"); }
private void addLessons(String lesson) { lessons.add(lesson); }
public ArrayList getLessons() { return lessons; } }
|
可见,以上我们将信息保存在了不同的聚合对象中,那么如果我们想要同时打印文理科的课程,该怎么办呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class PrintHelper { private LiberalLessons liberalLessons; private ScienceLessons scienceLessons;
public PrintHelper(LiberalLessons liberalLessons, ScienceLessons scienceLessons) { this.liberalLessons = liberalLessons; this.scienceLessons = scienceLessons; }
public void print() { printLiberalLessons(); printScienceLessons(); }
private void printLiberalLessons() { String[] lessons = liberalLessons.getLessons(); System.out.println("Liberal Lessons : "); for (int i = 0; i < LiberalLessons.MAX_LESSONS; i++) { System.out.print(lessons[i] + "\t"); } System.out.println(); }
private void printScienceLessons() { ArrayList<String> lessons = scienceLessons.getLessons(); System.out.println("Science Lessons : "); for (int i = 0; i < lessons.size(); i++) { System.out.print(lessons.get(i) + "\t"); } System.out.println(); } }
public class Client { public static void main(String[] args) { LiberalLessons liberalLessons = new LiberalLessons(); ScienceLessons scienceLessons = new ScienceLessons();
PrintHelper printHelper = new PrintHelper(liberalLessons, scienceLessons); printHelper.print(); } }
|
可见,在这里我又多写了一个辅助类 PrintHelper
, 这样可以减少主函数中的代码量。
来看看,由于我们使用了不同的聚合对象,导致我们不得不区别对待,如果有一种方法,能够让我们不管是针对哪种聚合对象都可以进行相同的操作就好了,这正是迭代器应该做的工作。
2 示例
首先,我们看看 java.util.Iterator
接口
1 2 3 4 5
| public interface Iterator<E> { boolean hasNext(); E next(); void remove(); }
|
hasNext()
方法返回一个布尔值,让我们知道是否还有更多的元素。
next()
方法返回下一个元素的值。
remove()
用于删除由 next()
方法返回的最后一项。
下面我们就利用Iterator
对以上代码进行改写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class LiberalIterator implements Iterator<String> {
private String[] lessons; private int position = 0;
public LiberalIterator(String[] lessons) { this.lessons = lessons; }
@Override public boolean hasNext() { if (position >= lessons.length) { return false; } return true; }
@Override public String next() { String lesson = lessons[position]; position += 1; return lesson; }
@Override public void remove() { throw new UnsupportedOperationException("You can not remove element !"); } }
|
我们针对文科课程类写了一个迭代器,在 remove()
方法中我们抛出了一个异常,表示我们不希望客户端通过迭代器删除元素。实际上我们也只需要写这么一个迭代器类,因为在 ScienceLessons
类中我们使用的是 ArrayList
,它是自带 Iterator
的,我们只需要调用 iterator()
方法即可。
接下来,我们就将 LiberalLessons
和 ScienceLessons
中的 getLessons()
方法进行改写,写成 createIterator()
方法。
1 2 3 4 5 6
| public Iterator<String> createIterator() { return new LiberalIterator(lessons); } public Iterator<String> createIterator() { return lessons.iterator(); }
|
现在再看看我们的 PrintHelper
该怎么书写代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class PrintHelper { private LiberalLessons liberalLessons; private ScienceLessons scienceLessons;
public PrintHelper(LiberalLessons liberalLessons, ScienceLessons scienceLessons) { this.liberalLessons = liberalLessons; this.scienceLessons = scienceLessons; }
public void print() { System.out.println("Liberal Lessons : "); Iterator<String> liberalIterator = liberalLessons.createIterator(); print(liberalIterator); System.out.println();
System.out.println("Science Lessons : "); Iterator<String> scienceIterator = scienceLessons.createIterator(); print(scienceIterator); System.out.println();
}
private void print(Iterator<String> iterator) { while (iterator.hasNext()) { System.out.print(iterator.next() + "\t"); } } }
|
这样的话,我们就可以不必区分聚合对象,只需要根据类中提供的迭代器就可以访问元素,而且这个时候我们也不知道类的内部用的是哪种聚合类型。
参考链接