迭代器模式
提供一种方法,顺序访问集合中的各种元素,而又不暴露该对象的内部表示。
理解
迭代器的精髓就是,我是一个容器,但是我不告诉你我具体是用什么实现的容器,同时,我给你一个对象,你可以用这个对象来遍历我这个容器。
迭代器模式很好的体现了封装和面向接口的编程思想。
一个图书馆的例子
我们都知道图书馆里会有很多本书。那么图书馆也算是一种容器,接下来我们用图书馆的例子来看看迭代器模式。
迭代器接口
首先我们定义一下迭代器和可迭代的这两个接口。凡是实现了可迭代的
接口的对象都得返回一个迭代器
对象。通过迭代器对象可以遍历容器。
-
Iterable
/** * 可迭代的 * @param <E> */ public interface Iterable<E> { /** * 获取一个迭代器 * @return */ Iterator<E> getIterator(); }
-
Iterator
/** * 迭代器 * @author skyline * @param <E> */ public interface Iterator<E> { /** * 是否有下一个 * @return */ boolean hasNext(); /** * 下一个 * @return */ E next(); }
图书馆对象
我们的图书馆本质上是个容器,同时需要实现Iterable
接口
/**
* 图书馆
* @author skyline
*/
public class Library implements Iterable<Book>{
private List<Book> books = new ArrayList<>();
@Override
public Iterator<Book> getIterator() {
return new LibraryIterator();
}
public void addBook(Book book){
books.add(book);
}
/**
* 图书馆迭代器
*/
private class LibraryIterator implements Iterator<Book>{
private int index=0;
@Override
public boolean hasNext() {
return index<books.size();
}
@Override
public Book next() {
Book book = books.get(index);
index++;
return book;
}
}
}
从上面的代码中可以看到,Library
其实就是一个List<Book>
的封装,而且LibraryIterator
每次进行遍历时,只是移动了一下index
而已。
main
public class IteratorMain {
private static final Logger logger = LoggerFactory.getLogger(IteratorMain.class);
public static void main(String[] args) {
Library library = new Library();
library.addBook(new Book("斯塔夫里阿诺斯","全球通史"));
library.addBook(new Book("司马迁","史记"));
library.addBook(new Book("孙武","孙子兵法"));
library.addBook(new Book("克劳塞维茨","战争论"));
library.addBook(new Book("比彻·斯托夫人","汤姆叔叔的小屋"));
library.addBook(new Book("司汤达","红与黑"));
library.addBook(new Book("雨果","悲惨世界"));
library.addBook(new Book("罗贯中","三国演义"));
Iterator<Book> iterator = library.getIterator();
while (iterator.hasNext()){
Book next = iterator.next();
logger.info("找到了一本书{}", next);
}
}
}
执行结果
思考
- 迭代器模式写起来挺简单的。
- 迭代器模式封装了容器内部的实现,使客户端代码不需要关心容器内部到底是如何实现的。
- 因为封装了容器的内部实现,所以就算是容器从ArrayList替换成了LinkedList,对于客户端代码来说,也没有任何改变。