0%

设计模式之Iterator模式

介绍

  • 意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
  • 关键实现: 定义接口Iterator:hasNext,next.
  • 优点
    • 它支持以不同的方式遍历一个聚合对象。
    • 迭代器简化了聚合类
    • 在同一个聚合上可以有多个遍历
    • 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码
  • 缺点:
    • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  • 使用场景:
    • 访问一个聚合对象的内容而无须暴露它的内部表示
    • 需要为聚合对象提供多种遍历方式
    • 为遍历不同的聚合结构提供一个统一的接口。
  • 注意事项:
    • 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

      实现

      VV

拿书架类举例:

名字 说明
Aggregate 表示集合的接口
Iterator 遍历集合的接口
Book 表示书的类
BookShelf 表示书架的类
BookShelfIterator 遍历书架的类
Main 测试程序行为的类

Aggregate.java

1
2
3
4
5
package com.edu.tju.GOF.Iterator;

public interface Aggregate {
public abstract Iterator iterator();
}

Iterator.java

1
2
3
4
5
6
7
package com.edu.tju.GOF.Iterator;

public interface Iterator {
public abstract boolean hasNext();

public abstract Object next();
}

Book.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.edu.tju.GOF.Iterator;

public class Book {
private String name;

public Book(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

BookShelf.java

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
package com.edu.tju.GOF.Iterator;

public class BookShelf implements Aggregate {
private Book[] books;
private int last = 0;

public BookShelf(int maxsize) {
this.books = new Book[maxsize];
}

public Book getBookAt(int index) {
return books[index];
}

public void appendBook(Book book) {
this.books[last] = book;
last++;
}

public int getLength() {
return last;
}

public Iterator iterator() {
return new BookShelfIterator(this);
}
}

BookShelfIterator.java

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
package com.edu.tju.GOF.Iterator;

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(index);
index++;
return book;
}
}

Main.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.edu.tju.GOF.Iterator;

public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("Around the World in 80 Days"));
bookShelf.appendBook(new Book("Bible"));
bookShelf.appendBook(new Book("Cinderella"));
bookShelf.appendBook(new Book("Daddy-Long-Legs"));
Iterator it = bookShelf.iterator();
while (it.hasNext()) {
Book book = (Book) it.next();
System.out.println(book.getName());
}
}
}

登场角色

  • Iterator (迭代器)
    该角色负责定义顺序逐个遍历元素的接口(API).在示例程序中,由Iterator接口扮演这个角色,它定义了hasNext 和 next两个方法.其中,hasNext方法用于判断是否存在下一个元素,next方法则用于获取该元素.
  • ConcreteIterator(具体的迭代器)
    该角色负责实现Iterator角色所定义的接口(API).在示例程序中,由BookShelfIterator类扮演这个角色.该角色中包含了遍历集合所需的信息.在示例程序中,BookShelf类的实例保存在bookShelf字段中,被指向的书的下标保存在index字段中.
  • Aggregate(集合)
    该角色负责创建Iterator角色的接口.这个接口是一个方法,会创建出”按顺序访问保存在我内部元素的人”.在实例程序中,由Aggregate接口扮演这个角色,它里面定义了iterator方法.
  • ConcreteAggregate(具体的集合)
    该角色负责实现Aggregate角色所定义的接口,它会创建出具体的Iterator角色.即ConcreteIterator角色,在实例程序中,由BookShelf类扮演这个角色.它实现了iterator方法.
  • Iterator模式的类图

扩展阅读

  1. python中的Iterator
    python中的Iterator模式

  2. 难以理解抽象类和接口
    难以理解抽象类和接口的人常常使用ConcreteAggregate角色和ConcreteIterator角色编程,而不使用Aggregate接口和Iterator接口,他们总想使用具体的类来解决所有的问题.
    但是如果只是用具体的类来解决问题,很容易导致类之间的强耦合,这些类也难以作为组件被再次利用.为了弱化类之间的耦合,进而使得类更加容易作为组件被再次利用,我们需要引入抽象类和接口.

不要只是用具体类来编程,要有先使用抽象类和接口来编程

  1. 迭代器的种类多种多样
  • 从最后开始向前遍历
  • 姐可以从前向后遍历,也可以从后向前遍历(既有next方法,也有previous方法)
  • 指定下标进行”跳跃式”遍历
Thank you for your support