什么是迭代器模式
迭代器模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
就好比如,你每天乘坐公交地铁,都是按顺序一个个排好队来,不需要关心你的身份,是男是女,还是其他...
类图:
场景
假设有这样一个场景:书架上有很多的书,这时候需要将名字按顺序显示出来;我们暂时不考虑java提供已有的api,我们程序应该如何去实现呢?大家可以一起想想
迭代器的主要角色
1. 迭代器(Iterator)
在示例中,Iterator代表了迭代器的角色,主要是提供了api接口,存在两个api接口,分别是hasNext作用在于是否存在下一个元素,next方法作用在于获取元素。
public interface Iterator {
/**
* 是否拥有下一个元素
* @return
*/
boolean hasNext();
/**
* 下一个元素
* @return
*/
Object next();
}
2. 具体迭代器(Concretelterator)
在示例中,BookShelfIterator表示具体迭代器角色,它实现了Iterator,该角色中存在需要遍历的bookShelf(书架),以及一个下标的字段,该字段要作用是为了标注遍历的位置。
public class BookShelfIterator implements Iterator{
private BookShelf bookShelf;
private int index;
public BookShelfIterator(BookShelf bookShelf){
this.bookShelf = bookShelf;
this.index = 0;
}
@Override
public boolean hasNext() {
if (index < bookShelf.getLength()){
return true;
}else{
return false;
}
}
@Override
public Object next() {
Book book = bookShelf.getAt(index);
index++;
return book;
}
}
3. 集合(Aggregate)
示例中,Aggregate表示集合,读者可以暂且把它理解为List,里面有一个iterator迭代方法,返回值为实现Iterator接口的实例,即具体迭代器。
public interface Aggregate {
/**
* 集合的迭代器
* todo:思考:它的作用是什么,为什么要这么做
* @return
*/
Iterator iterator();
}
4. 具体的集合(ConcreteAggregate)
示例中,BookShelf表示具体的集合,它实现了Aggregate,该角色实现了iterator迭代方法。
public class BookShelf implements Aggregate{
private Book[] books;
private int lastIndex = 0;
public BookShelf(int maxSize){
this.books = new Book[maxSize];
}
public Book getAt(int index){
return books[index];
}
public void appendBook(Book book){
this.books[lastIndex] = book;
lastIndex++;
}
public int getLength(){
return lastIndex;
}
@Override
public Iterator iterator() {
return new BookShelfIterator(this);
}
}
其他代码:
实体类
public class Book {
private String name;
private String price;
//set get....
}
mian方法测试:
public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book(){{setName("水浒传");}});
bookShelf.appendBook(new Book(){{setName("西游记");}});
bookShelf.appendBook(new Book(){{setName("红楼梦");}});
bookShelf.appendBook(new Book(){{setName("三国演义");}});
Iterator it = bookShelf.iterator();
while (it.hasNext()){
System.out.println(it.next().toString());
}
}
}
看完上述代码之后,我们再理解一下
首先该模式有四大角色:两个接口,两个实现,且Aggregate接口使用了Iterator接口,那么问题就来了,为啥要使用,那我们接着看实现Aggregate的实现,即BookShelf(书架),遍历书架上的书,自然在书架上进行遍历,所以不难解释为啥Aggregate接口使用了Iterator接口。迭代的实现交给了BookShelfIterator,将BookShelf(书架)赋值给BookShelfIterator中的bookShelf字段,BookShelfIterator通过实现的hasNext与next方法,对BookShelf进行依次迭代的一个过程。
序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的(这里的底层结构是指容器结构如数组,我们的示例中books就是数组对象)。只要拿到这个对象(指BookShelf),使用迭代器就可以遍历这个对象的内部。
思考点:
1. 增强for循环与迭代器
- 增强for用来处理集合中的每个元素而不用考虑集合定下标。简化了 Iterator 的书写。
- 增强for循环和iterator遍历的效果是一样的,也就说增强for循环的内部也就是调用iteratoer实现的,但是增强for循环有些缺点,例如不能在增强循环里动态的删除集合内容、不能获取下标等。
2. 什么场景需要用到
在日常开发中,我们很少写自己的迭代器。除非需要定制一个自己实现的数据结构对应的迭代器,否则,开源框架提供的 API 完全够用。
3. 为什么要用如此多的接口
解耦,具体类虽然可以解决我们的问题,但是难以被再次利用,为了弱化类与类之间的耦合关系,我们需要要引入大量的抽象类和接口,另外就是抽象思维很重要,能够让代码可维护性以及扩展性得到增强,不理解没关系,我们时时记着。其实我也不太理解,很多书都这样说...
参考资料《图解设计模式》