Java设计模式之 Iterator 迭代器模式
设计模式本身就是一门玄学,看不懂很正常,一次看懂就不是很正常了,多看多练才是关键
int [] array = {1 , 2 , 3 , 4 , 5 , 6};
for(int i = 0;i < array.length;i++) {
System.out.println(array[i]);
}
看这个代码是不是平平无奇,是的,它就是平平无奇的遍历和输出而已,其中变量 i 的作用就是确定当前对数组的索引,然后将这里的循环变量i的作用抽象化、通用化之后形成的模式,在设计模式中称为Iterator;Iterator模式用于在数据集合中按照顺序遍历集合,汉语称为“迭代器”;
新建一个项目开始代码部分
接口类Aggregate.java
public interface Aggregate { //所要遍历的集合的接口,实现了该接口的类将成为一个可以保存多个元素的集合,就像数组一样
public abstract Iterator iterator(); //该方法生成一个用于遍历集合的迭代器
}
接口类Iterator.java
public interface Iterator { //用于遍历集合中的元素,其作用相当于循环语句中的循环变量
public abstract boolean hasNext(); //判断是否存在下一个元素
public abstract Object next(); //获取下一个元素,返回类型为Object,
}
简单类Book.java
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
实现接口Aggregate类BookShelf.java
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);
}
}
实现接口Iterator类BookShelfIterator.java
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;
}
}
测试运行类Iterator_Main .java
public class Iterator_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 iterator = bookShelf.iterator();
while (iterator.hasNext()) {
Book book = (Book) iterator.next();
System.out.println(book.getName());
}
}
}
个人理解:
你看呀,书架原本就有不少的功能,包括:加书、按位置取书、获取书的数量,第一个接口被书架继承之后,书架重写了它的方法之后,就相当于在书架上多安装了一个组件,这个组件包含:浏览屏幕和“下一页”按钮,这个组件就是迭代器!
Iterator iterator = bookShelf.iterator();
这一句代码可就是关键了呀,我们并不直接对这个书架进行翻阅寻找,而是通过我们之前所提供的迭代器进行工作!就是我们不用自己直接去找书,而是有个大傻个帮我们去拿!
类和接口一览表
名字 | 说明 |
---|---|
Aggregate | 表示集合的接口 |
Iterator | 遍历集合的接口 |
Book | 表示书的类 |
BookShelf | 表示书架的类 |
BookShelfIterator | 遍历书架的类 |
Iterator_Main | 测试程序行为的类 |
Iterator中的角色
·Iterator(迭代器)
该角色负责定义按顺序逐个遍历元素的接口(API)。在示例程序中,由Iterator接口扮演这个角色,它定义了hasNext和next两个方法。
·ConcreteIterator(具体的迭代器)
该角色负责实现Iterator角色所定义的接口。在示例程序中,由BookShelfIterator类扮演这个角色,该角色中包含了遍历结合所必需的信息。
·Aggregate(集合)
该角色负责定义创建Iterator角色的接口。这个接口是一个方法,会创建出“按顺序访问保存在我内部元素的人”。在示例程序中,由Aggregate接口扮演这个角色。
·ConcreteAggregate(具体的集合)
该角色负责实现Aggregate角色所定义的接口。它会创建出具体的Iterator角色,即ConcreteIterator角色,在示例程序中,由BookShelf接口扮演这个角色
为什么要引入Iterator这种复杂的设计模式?
引入Iterator后可以将遍历与实现分离
正如代码中所展示的,while的循环并不依赖于BookShelf的实现,不管BookShelf如何变化,只要BookShelf的iterator方法能正确的返回Iterator的实例,即使不对上面的while循环做任何修改,代码可以正常工作,大大提高了可复用性
难以理解抽象类和接口
难以理解抽象类和接口的人常常使用具体的类来解决所有问题,容易导致类之间的强耦合,这些类也难以作为组件被再次利用
不需要deleteIterator,在java中,没有被使用的对象实例将会自动被回收
相关的设计模式
Visitor模式(在遍历元素结合的过程中,对元素进行相同的处理)
Composite模式(具有递归结构的模式)
Factory Method模式(在iterator方法中生成Iterator的实例时可能会使用到这个模式)
相关习题:
在示例程序的BookShelf类中,当书的数量超过最初指定的书架容量时,就无法继续向书架中添加书本了。请大家不使用数组,而是用java.util.ArrayList修改程序,确保当书的数量超过最初指定的书架容量时也能继续向书架中添加书本
答案(不唯一)
修改BookShelf.java中的代码:(测试程序中自己手动随便加几本书就行了)
import java.util.ArrayList;
public class BookShelf implements Aggregate {
private ArrayList books;
public BookShelf(int initialsize) {
this.books = new ArrayList(initialsize);
}
public Book getBookAt(int index) {
return (Book)books.get(index);
}
public void appendBook(Book book) {
books.add(book);
}
public int getLength() {
return books.size();
}
public Iterator iterator() {
return new BookShelfIterator(this);
}
}