迭代器模式: 提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。
比如說,現在我們有兩個聚合對象,一個是數組,一個是 ArrayList
, 利用這兩個對象分別存儲文理科課程信息,像下面這樣。
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;
}
}
可見,以上我們將信息保存在了不同的聚合對象中,那么如果我們想要同時打印文理科的課程,該怎么辦呢?
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
, 這樣可以減少主函數中的代碼量,我個人不太喜歡在主函數寫太多的代碼。
來看看,由于我們使用了不同的聚合對象,導致我們不得不區別對待,如果有一種方法,能夠讓我們不管是針對哪種聚合對象都可以進行相同的操作就好了,這正是迭代器應該做的工作。
首先,我們看看 java.util.Iterator
接口
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
hasNext()
方法返回一個布爾值,讓我們知道是否還有更多的元素。
next()
方法返回下一個元素的值。
remove()
用于刪除由 next()
方法返回的最后一項。
下面我們就利用Iterator
對以上代碼進行改寫。
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()
方法。
public Iterator<String> createIterator() {
return new LiberalIterator(lessons);
}
public Iterator<String> createIterator() {
return lessons.iterator();
}
現在再看看我們的 PrintHelper
該怎么書寫代碼。
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");
}
}
}
這樣的話,我們就可以不必區分聚合對象,只需要根據類中提供的迭代器就可以訪問元素,而且這個時候我們也不知道類的內部用的是哪種聚合類型。