本文節選自《設計模式就該這樣學》
迭代器模式的UML類圖如下圖所示。
1 手寫自定義的集合迭代器
總體來說,迭代器模式是非常簡單的。還是以網路課程為例,我們建立一個課程集合,集合中的每一個元素都是課程物件,然後手寫一個迭代器,將每一個課程物件的資訊都讀出來。首先建立集合元素課程Course類。
public class Course {
private String name;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
然後建立自定義迭代器Iterator介面。
public interface Iterator<E> {
E next();
boolean hasNext();
}
建立自定義的課程集合CourseAggregate介面。
public interface CourseAggregate {
void add(Course course);
void remove(Course course);
Iterator<Course> iterator();
}
接著分別實現迭代器介面和集合介面,建立IteratorImpl實現類。
public class IteratorImpl<E> implements Iterator<E> {
private List<E> list;
private int cursor;
private E element;
public IteratorImpl(List list){
this.list = list;
}
public E next() {
System.out.print("當前位置" + cursor + ": ");
element = list.get(cursor);
cursor ++;
return element;
}
public boolean hasNext(){
if(cursor > list.size() - 1){
return false;
}
return true;
}
}
建立課程集合CourseAggregateImpl實現類。
public class CourseAggregateImpl implements CourseAggregate {
private List courseList;
public CourseAggregateImpl() {
this.courseList = new ArrayList();
}
public void add(Course course) {
courseList.add(course);
}
public void remove(Course course) {
courseList.remove(course);
}
public Iterator<Course> iterator() {
return new IteratorImpl(courseList);
}
}
最後編寫客戶端測試程式碼。
public static void main(String[] args) {
Course java = new Course("Java架構");
Course javaBase = new Course("Java入門");
Course design = new Course("Java設計模式精講");
Course ai = new Course("人工智慧");
CourseAggregate courseAggregate = new CourseAggregateImpl();
courseAggregate.add(java);
courseAggregate.add(javaBase);
courseAggregate.add(design);
courseAggregate.add(ai);
System.out.println("-----課程列表-----");
printCourses(courseAggregate);
courseAggregate.remove(ai);
System.out.println("-----刪除操作之後的課程列表-----");
printCourses(courseAggregate);
}
public static void printCourses(CourseAggregate courseAggregate){
Iterator<Course> iterator = courseAggregate.iterator();
while(!iterator.hasNext()){
Course course = iterator.next();
System.out.println("《" + course.getName() + "》");
}
}
執行結果如下圖所示。
看到這裡,小夥伴們肯定有一種似曾相識的感覺,讓人不禁想起每天都在用的JDK自帶的集合迭代器。下面就來看原始碼中是如何運用迭代器的。
2 迭代器模式在JDK原始碼中的應用
先來看JDK中大家非常熟悉的Iterator原始碼。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
從上面程式碼中,我們看到定義了兩個主要方法hasNext()方法和next()方法,和我們自己寫的完全一致。
另外,從上面程式碼中,我們看到remove()方法實現似曾相識。其實是在組合模式中見過的。迭代器模式和組合模式兩者似乎存在一定的相似性,組合模式解決的是統一樹形結構各層次訪問介面,迭代器模式解決的是統一各集合物件元素遍歷介面。雖然它們的適配場景不同,但核心理念是相通的。
接著來看Iterator的實現類,其實在我們常用的ArrayList中有一個內部實現類Itr,它實現了Iterator介面。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
...
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
...
}
...
}
其中,hasNext()方法和next()方法的實現也非常簡單,繼續往下看,在ArrayList內部還有幾個迭代器對Itr進行了進一步擴充套件,首先看ListItr。
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
...
}
它增加了hasPrevious()方法,主要用於判斷是否還有上一個元素。另外,還有SubList對子集合的迭代處理。
3 迭代器模式在MyBatis原始碼中的應用
當然,迭代器模式在MyBatis中也是必不可少的,來看一個DefaultCursor類。
public class DefaultCursor<T> implements Cursor<T> {
...
private final CursorIterator cursorIterator = new CursorIterator();
...
}
它實現了Cursor介面,而且定義了一個成員變數cursorIterator,其定義的型別為CursorIterator。繼續檢視CursorIterator類的原始碼發現,它是DefaultCursor的一個內部類,並且實現了JDK中的Iterator介面。
關注微信公眾號『 Tom彈架構 』回覆“設計模式”可獲取完整原始碼。
本文為“Tom彈架構”原創,轉載請註明出處。技術在於分享,我分享我快樂!
如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支援是我堅持創作的動力。關注微信公眾號『 Tom彈架構 』可獲取更多技術乾貨!