设计模式之迭代器模式
GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
它的目的:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。[GOF 《设计模式》]
如果大家只看定义的话估计也不太清楚吧,怎么说呢,从简单来讲,大家可以把它理解为是一个抽象化的for循环语句。
for语句:
for(int i=0;i<arr.length;i++){ System.out.printIn(arr[i]); }
模式结构图
Iterator模式结构图如下:
有下面四个角色:
1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。
2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。
下面我们通过一个简单的例子来实现:
首先看一下类图:
下面我贴上代码:
public interface Aggregate { public abstract Iterator iterator(); }
public interface Interator { public abstract boolean hasNext(); public abstract Object next(); }
public class Book { private String name = ""; public Book(String name) { this.name=name; } public String getName(){ return name; } }
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; } @Override public Iterator iterator() { return new BookShelfIterator(this); } }
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.getBookAt(index);// 得到当前位置的book index++;// 进到下一个位置的book return book; } @Override public void remove() { // TODO Auto-generated method stub } }
public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("A")); bookShelf.appendBook(new Book("B")); bookShelf.appendBook(new Book("C")); bookShelf.appendBook(new Book("D")); Iterator it = bookShelf.iterator(); while (it.hasNext()) { Book book = (Book) it.next(); System.out.println("" + book.getName()); } } }
测试结果:
一个简单的容器为什么还要定义成一个接口呢?
如果对如何使用抽象类和接口还不太清楚的话,估计会很纠结于这个问题。因为只用具体类就能解决所有问题的感觉会让人不知不觉的上瘾。
其实原因很简单,过度依赖具体类会提高类与类的耦合度,增加零部件复用的困难。为了降低耦合度,让类作为零部件再利用,必须引进抽象类和接口的概念。也就是实现软件的“高内聚低耦合”,这是以前软件工程老师常提到的话了。
迭代器模式的优点:
- 它支持以不同的方式遍历一个聚合对象 : 复杂的聚合可用多种方式进行遍历。迭代器模式使得改变遍历算法变得很容易 : 仅需用一个不同的迭代器的实例代替原先的实例即可。你也可以自己定义迭代器的子类以支持新的遍历。
- 迭代器简化了聚合的接口 有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了。这样就简化了聚合的接口。
- 在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。
迭代器模式的缺点:
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
迭代器模式的适用范围:
- 访问一个容器对象的内容而无需暴露它的内部表示。
- 支持对容器对象的多种遍历。
- 为遍历不同的容器结构提供一个统一的接口(多态迭代)。
总结:
Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。
文章出处:http://www.cnblogs.com/scetopcsa/
欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
如果文中有什么错误,欢迎指出。以免更多的人被误导。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。