據說微信搜索《Java魚仔》會變動強哦!java
本文收錄於JavaStarter ,裏面有我完整的Java系列文章,學習或面試均可以看看哦git
(一)什麼是迭代器模式
迭代器模式應該是23種設計模式中,程序員最容易理解的設計模式了,由於迭代器模式在平常的開發過程當中常用到。以最多見的循環爲例:程序員
for(int i=0;i<arr.length;i++){ System.out.print(arr[i]); }
上面的這段代碼經過循環逐一將arr的下標加1,從而實現了遍歷數組的功能。github
可是經過循環實現遍歷的話依賴於集合對象內部,所以就有了一種能順序訪問集合對象中各個元素,又無需依賴對象內部表示的設計模式--迭代器模式。面試
(二)迭代器模式中的角色
迭代器模式中的角色主要有4種:設計模式
一、迭代器接口(Iterator):定義訪問和遍歷集合元素的接口,通常包含next()和hasNext()方法。數組
二、具體迭代器(ConcreteIterator):該角色用於實現迭代器接口,迭代器的核心遍歷邏輯在這裏實現。微信
三、集合接口(Aggregate):集合接口定義了建立迭代器的接口方法,內部定義了iterator方法。ide
四、具體集合(ConcreteAggregate):該角色用於實現集合接口,他會建立出具體的Iterator角色。學習
看到這裏若是你以爲比較疑惑沒關係,下面會經過代碼的方式來加深理解。
(三)迭代器模式的代碼實現
首先說一下這段代碼的場景,定義了一個教室的類,又定義了學生的類,實現遍歷教室中學生的功能。
代碼列表以下:
interface Aggregate:集合接口 interface Iterator:迭代器接口 class Classroom:教室類,實現集合接口,屬於具體的集合 class ClassroomIterator:教室迭代器,實現迭代器接口,屬於具體的迭代器 class Student:學生類
首先把迭代器模式中的兩個接口角色定義出來:
public interface Aggregate { Iterator iterator(); } public interface Iterator { boolean hasNext(); Object next(); }
接着定義學生類:
@Data @AllArgsConstructor public class Student { private String name; }
接着定義教室類,在教室類中咱們定義了Student集合,以及當前的集合長度和最大長度。同時實現Aggregate接口的iterator方法,這個方法將會返回一個迭代器對象。這個迭代器對象由ClassroomIterator提供
public class Classroom implements Aggregate{ private Student[] students; private int length=0; private int maxSize; public Classroom(int maxSize){ this.maxSize=maxSize; students=new Student[maxSize]; } public Student getStudent(int index){ return students[index]; } public boolean addStudent(Student student){ if (length>=maxSize){ return false; } this.students[length]=student; length++; return true; } public int getLength(){ return this.length; } @Override public Iterator iterator() { return new ClassroomIterator(this); } }
最後就是ClassroomIterator對象了,ClassroomIterator屬於迭代器的具體實現,這裏須要實現hasNext方法和next方法
public class ClassroomIterator implements Iterator{ private Classroom classroom; private int index; public ClassroomIterator(Classroom classroom){ this.classroom=classroom; this.index=0; } @Override public boolean hasNext() { if (this.index<classroom.getLength()){ return true; } return false; } @Override public Object next() { Student student = classroom.getStudent(index); index++; return student; } }
最後就是使用了,經過迭代器對象,咱們能夠直接遍歷classroom對象:
public static void main(String[] args) { Classroom classroom=new Classroom(3); classroom.addStudent(new Student("張三")); classroom.addStudent(new Student("李四")); classroom.addStudent(new Student("王五")); Iterator iterator = classroom.iterator(); while (iterator.hasNext()){ Student next = (Student) iterator.next(); System.out.println(next.getName()); } }
(四)迭代器模式的做用
看到這裏不少人可能會有疑問,寫了一堆,用循環不是更方便嗎?迭代器模式最大的做用是將遍歷和具體的實現分開,以上面的測試方法爲例,遍歷時咱們始終只用到了iterator對象,而沒有用到classroom,這就意味着咱們以後能夠徹底複用這段代碼實現遍歷。
另外一方面,若是咱們發如今classroom裏使用數組存儲student,後續沒法擴容,想改成List集合,這個時候咱們只須要修改ClassroomIterator和Classroom這兩個具體實現角色便可。而不用對使用中的代碼作任何修改,就好比上面這段測試遍歷代碼不須要任何變更。若是用的是for循環或者while循環,就意味着全部用到循環的地方都須要修改代碼。
(五)迭代器模式在源碼中的應用
迭代器模式的應用咱們在敲代碼時確定都用過,迭代器模式最佳實踐就是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()); } }
具體的迭代器實現最經常使用的就是集合,隨便找個ArrayList看一下源碼:
總體的實現邏輯和咱們上面實現的基本上十分類似。
(五)總結
在學習設計模式的時候,會慢慢開始理解爲何要設計接口,而不是直接寫各類類。若是用具體的類去解決一個個需求,就會致使類之間的強依賴,這些類也難以被拆分出來做爲組件複用。我是魚仔,咱們下期再見!