Iterator模式
看《图解设计模式》一书,做个笔记。
如何遍历一个数组?大多数语言可以使用 for
循环来轻松实现这一需求。for
循环我们可能再熟悉不过了。1
2
3for ( int i = 0; i < arr.length; ++i){
System.out.println(arr[i]) //java
}
Python语言中有迭代器这一说,用来遍历可迭代的对象。例如以下例程:1
2
3
4
5
6it = iter( (1, 3, 5, 7, 9) ) #生成迭代器对象
while True:
try:
print( next(it) ) #获得下一个值
except StopIteration: #捕获停止迭代的异常,跳出循环
break
对于迭代器,就是实现遍历可迭代对象的工作。这个可迭代对象,个人理解可以是数组,集合,或者是一些其他复杂的结构。所有的这种可迭代对象都可以抽象为 next()
和 hasNext()
即下一个和判断是否有下一个元素的两个方法。(比如上面 python
语言中 next()
函数和 StopIteration
异常就是对应的这两个方法,只不过实现起来不同语言可能不一样)。所以,对于迭代器设计模式,我们可以首先抽象出 Iterator
接口。1
2
3
4
5
6
7//Iterator.java
package com.company;
public interface Iterator {
public abstract boolean hasNext(); //判断对象是否迭代结束
public abstract Object next(); //返回当前元素,并将指针向后移动一个单位
}
这样,我们抽象出了 Iterator接口
,对于可迭代的对象,我们可以使用实现这个借口的方式进而实现我们的迭代器设计模式。下面我们用书架和书这个关系来说说这个迭代器模式的设计思路。(参考书目《图解设计模式》)
首先,我们可以定义书这个class:1
2
3
4
5
6
7
8
9
10
11
12
13
14//Book.java
package com.company;
public class Book {
private String name;
public Book (String name){
this.name = name;
}
public String getName () {
return this.name;
}
}
接着,在声明书架这个 class 之前,我们还要定义一个 Aggregate
接口,个人理解这个借口的作用是用来生成迭代器对象的接口。1
2
3
4
5
6
7//Aggregate.java
package com.company;
//表示集合的接口
public interface Aggregate {
public abstract Iterator iterator();
}
接下来就是实现书架这一class,来实现上面的 Aggregate
接口。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//BookShelf.java
package com.company;
public class BookShelf implements Aggregate {
private Book[] books; //数组来储存书的条目
private int last = 0; //last来标记books[]最末元素的索引值
public BookShelf (int maxSize){
this.books = new Book[maxSize];
}
public Book getBookAt (int index){
return this.books[index];
}
public void appendBook (Book book){
this.books[last] = book;
++last;
}
public int getLength () {
return this.last;
}
public Iterator iterator () {
return new BookShelfIterator(this);
}
}
最后的 iterator()
返回了 BookShelfIterator
对象,也就是我们一直说的迭代器,接下来通过实现 Iterator
来实现 BookShelfIterator
对象。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//BookShelfIterator.java
package com.company;
public class BookShelfIterator implements Iterator{
private BookShelf bookShelf;
private int index;
public BookShelfIterator (BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
public boolean hasNext () {
if(index < bookShelf.getLength())
return true;
else
return false;
}
public Object next () {
Book book = bookShelf.getBookAt(this.index);
index++;
return book;
}
}
这个 BookShelfIterator
class 具体的实现了 Iterator
接口中的两个方法,即可通过 Aggregate
中的 iterator()
生成迭代器,在通过 next()
和 hasNext()
来实现迭代,在 Main
class 中可以对我们的代码进行测试。
1 | package com.company; |
最后说说我的对 Iterator
模式的理解,这可以使得不同的可迭代对象比如,Vector,ArrayList 什么鬼的东西,使用者只需要 hasNext()
和 next()
两个 function
来遍历即可。具体的实现交给 BookShelfIterator
class,我们只需要编写不同的 class 来实现不同的需求,甚至我们可以自定义迭代的规则,正序或反序,或者“跳跃式“迭代等等需求。然而这些大大方便了使用者去调用。
最后附上书中的两张图