Hexo

点滴积累 豁达处之

0%

17 迭代器模式

​ 迭代器模式: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

迭代器模式

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");
}
}
}

​ 这样的话,我们就可以不必区分聚合对象,只需要根据类中提供的迭代器就可以访问元素,而且这个时候我们也不知道类的内部用的是哪种聚合类型。

参考链接