Iterator模式 --一个一个遍历
在Java中的for语句中 i++的作用是让 i 的值在每次循环后自增1,这样就可以访问数组中的下一个元素、下下一个元素、再下下一个元素,也就实现了从头至尾逐一遍历数组元素的功能。
将这里的循环变量 i的作用抽象化、通用化后形成的模式,在设计模式中称为 Iterator 模式。
示例程序
- Aggregate接口
Aggregate接口是索要遍历的集合的接口。实现了该接口的类将称为一个可以保持多个元素的集合。
public interface Aggregate { public abstract Iterator iterator(); }
Aggregate接口中的iterator 方法将会生成一个用于遍历集合的迭代器。想要遍历集合中的元素的时候可以调用该方法来生成一个实现了Iterator接口的类的实例。
- Iterator接口
public interface Iterator { public abstract boolean hasNext(); public abstract Object next(); }
hasNext()方法主要用于循环终止条件。
next()方法用于返回集合中的一个元素,并且为了在下次调用next方法时正确地反回下一个元素,在该方法中还需将迭代器移动至下一个元素的处理。
- Book类
public class Book { private String name; public Book(String name) { this.name = name; } public String getName() { return name; } }
- BookShelf类
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 Itrator iterator() { return new BookShelfIterator(this); } }
BookShelf类是用来表示书架的类,将该类作为Book的集合进行处理,实现了Aggregate接口。
- BookShelfIterator类
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; } }
BookShelfIterator类是一个迭代器的实现,它持有一个将要遍历的集合BookShelf书架。
- Main类
public class Main{ public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("倚天屠龙记")); bookShelf.appendBook(new Book("葵花宝典")); bookShelf.appendBook(new Book("九阳真经")); bookShelf.appendBook(new Book("神雕侠侣")); Iterator it = bookShelf.iterator(); while (it.hasNext()){ Book book = (Book) it.next(); System.out.println(book.getName()); } } }
总结
- 为何要使用Iterator
引入Iterator后可以将遍历与实现分离开来,在遍历时只需调用迭代器的方法,而不用关心具体集合实现类的方法。假设以后需要对集合类的实现方式进行修改,只要集合中的Iterator方法能正确的返回Iterator实例,即使不对迭代器的使用者进行修改,遍历代码都能正常工作。
设计模式的作用就是帮助我们编写可复用的类。“可复用”就是将类实现为“组件”,当一个组件发生改变时,不需要对其他的组件进行修改或只需很小的修改即可应对。
- 多个Iterator
将遍历功能置于Aggregate角色之外,是Iterator模式的一个特征。根据这几个特征,可以针对一个具体的ConcreateAggregate角色编写多个ConcreteIterator角色。
- 对JAVA集合进行遍历删除时务必要用迭代器。
1 private class Itr implements Iterator<E> { 2 /** 3 * Index of element to be returned by subsequent call to next. 4 */ 5 int cursor = 0; 6 /** 7 * Index of element returned by most recent call to next or 8 * previous. Reset to -1 if this element is deleted by a call 9 * to remove. 10 */ 11 int lastRet = -1; 12 /** 13 * The modCount value that the iterator believes that the backing 14 * List should have. If this expectation is violated, the iterator 15 * has detected concurrent modification. 16 */ 17 int expectedModCount = modCount; 18 public boolean hasNext() { 19 return cursor != size(); 20 } 21 public E next() { 22 checkForComodification(); 23 try { 24 E next = get(cursor); 25 lastRet = cursor++; 26 return next; 27 } catch (IndexOutOfBoundsException e) { 28 checkForComodification(); 29 throw new NoSuchElementException(); 30 } 31 } 32 public void remove() { 33 if (lastRet == -1) 34 throw new IllegalStateException(); 35 checkForComodification(); 36 try { 37 AbstractList.this.remove(lastRet); 38 if (lastRet < cursor) 39 cursor--; 40 lastRet = -1; 41 expectedModCount = modCount; 42 } catch (IndexOutOfBoundsException e) { 43 throw new ConcurrentModificationException(); 44 } 45 } 46 final void checkForComodification() { 47 if (modCount != expectedModCount) 48 throw new ConcurrentModificationException(); 49 } 50 }