1. 程式人生 > >設計模式初探-迭代器模式(ITERATOR)又稱遊標(Cursor)

設計模式初探-迭代器模式(ITERATOR)又稱遊標(Cursor)

迭代器模式(ITERATOR),又稱遊標(Cursor),提供了一種方法,用於順序訪問一個聚合物件中的各個元素,而不需暴露該物件的內部表示,屬於物件行為型模式。迭代器模式通過將對聚合物件(通常為列表)的訪問和遍歷從聚合物件中分離出來並放入一個迭代器物件中,迭代器物件知道如何遍歷列表,這樣不僅可以簡化聚合物件的實現(將遍歷操作交給迭代器負責,自己只負責儲存),還可以以不同的方式遍歷列表。

一、使用場景

1、訪問一個聚合物件的內容而無需暴露它的內部表示。

2、支援對聚合物件的多種遍歷,比如正向遍歷,逆向遍歷,JDK的迭代器只實現正向遍歷。

3、為遍歷不同的聚合結構提供一個統一的介面。對不同的聚合結構只需切換要遍歷的物件而不需改變遍歷過程的程式碼。

二、UML圖

迭代器模式

三、Java實現

  1. package study.patterns.iterator;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. /** 
  5.  * 迭代器模式,為遍歷聚合結構而生!  
  6.  * 迭代器模式通常使用工廠方法模式來例項化適當的迭代器子類。 
  7.  * @author qbg 
  8.  */
  9. publicclass IteratorPattern {  
  10.     publicstaticvoid main(String[] args) {  
  11.         List<String> list = new
     ArrayList<String>();  
  12.         list.add("Java程式設計思想");  
  13.         list.add("設計模式");  
  14.         list.add("程式設計匠藝");  
  15.         list.add("重構");  
  16.         AbstractList<String> books = new ConcreteList<String>(list);  
  17.         Iterator<String> iterator = books.iterator();  
  18.         System.out.println("=======正向遍歷==========="
    );  
  19.         while(iterator.hasNext()){  
  20.             System.out.print(iterator.next()+",");  
  21.         }  
  22.         System.out.println("\n=======逆向遍歷===========");  
  23.         while(iterator.hasPrevious()){  
  24.             System.out.print(iterator.previous()+",");  
  25.         }  
  26.     }  
  27. }  
  28. /** 
  29.  * 抽象聚合類 
  30.  * @param <E> 
  31.  */
  32. abstractclass AbstractList<E>{  
  33.     protected List<E> elements = new ArrayList<E>();  
  34.     public AbstractList(List<E> eles){  
  35.         this.elements = eles;  
  36.     }  
  37.     publicvoid add(E e){  
  38.         elements.add(e);  
  39.     }  
  40.     publicvoid remove(E e){  
  41.         elements.remove(e);  
  42.     }  
  43.     public List<E> getAll(){  
  44.         return elements;  
  45.     }  
  46.     /** 
  47.      * 宣告建立迭代器物件的抽象工廠方法 
  48.      */
  49.     publicabstract Iterator<E> iterator();  
  50. }  
  51. /** 
  52.  * 具體聚合類,建立基於該聚合類的迭代器 
  53.  * @param <E> 
  54.  */
  55. class ConcreteList<E> extends AbstractList<E>{  
  56.     public ConcreteList(List<E> eles) {  
  57.         super(eles);  
  58.     }  
  59.     @Override
  60.     public Iterator<E> iterator() {  
  61.         returnnew ConcreteIterator<E>(this);  
  62.     }  
  63. }  
  64. /** 
  65.  * 遍歷器抽象介面,支援泛型 
  66.  */
  67. interface Iterator<E>{  
  68.     /** 
  69.      * 正向遍歷,判斷是否有後繼節點 
  70.      */
  71.     publicboolean hasNext();  
  72.     /** 
  73.      * 遊標下移,返回遊標越過的元素引用  
  74.      */
  75.     public E next();  
  76.     /** 
  77.      * 逆向遍歷,判斷是否有前驅節點  
  78.      */
  79.     publicboolean hasPrevious();  
  80.     /** 
  81.      * 遊標上移,返回遊標越過的元素引用 
  82.      */
  83.     public E previous();  
  84. }  
  85. /** 
  86.  *  具體迭代器,用於遍歷AbstractList<E>集合. 
  87.  *  支援正向遍歷和逆向遍歷  
  88.  * @param <E> 
  89.  */
  90. class ConcreteIterator<E> implements Iterator<E>{  
  91.     private AbstractList<E> list;//要遍歷的集合
  92.     private List<E> elements;//集合中的元素
  93.     privateint cursor_forword;//正向遍歷的遊標,用於記錄正向遍歷的位置
  94.     privateint cursor_backword;//逆向遍歷的遊標,用於記錄逆向遍歷的位置
  95.     public ConcreteIterator(AbstractList<E> list){  
  96.         this.list = list;  
  97.         this.elements = this.list.getAll();//獲取集合元素
  98.         this.cursor_forword = 0;//設定正向遍歷遊標初始值
  99.         this.cursor_backword = elements.size()-1;//設定逆向遍歷遊標初始值
  100.     }  
  101.     @Override
  102.     publicboolean hasNext() {  
  103.         return cursor_forword < elements.size();  
  104.     }  
  105.     @Override
  106.     public E next() {  
  107.         E e = elements.get(cursor_forword);  
  108.         cursor_forword++;  
  109.         return e;  
  110.     }  
  111.     @Override
  112.     publicboolean hasPrevious() {  
  113.         return cursor_backword >= 0;  
  114.     }  
  115.     @Override
  116.     public E previous() {  
  117.         E e = elements.get(cursor_backword);  
  118.         cursor_backword--;  
  119.         return e;  
  120.     }  
  121. }  
執行結果:
  1. =======正向遍歷===========  
  2. Java程式設計思想,設計模式,程式設計匠藝,重構,  
  3. =======逆向遍歷===========  
  4. 重構,程式設計匠藝,設計模式,Java程式設計思想,  

四、模式優缺點

優點:

1、支援以不同的方式遍歷一個聚合。想改變遍歷方式只需用一個不同的迭代器例項代替原先的例項即可。

2、迭代器簡化聚合的介面。有了迭代器的遍歷介面,聚合本身就不需要類似的遍歷介面了。

3、在同一個聚合上可以有多個遍歷。每個迭代器保持它自己的遍歷狀態,互不影響。

缺點:

1、抽象迭代器的設計比較難以把握,如果前期設計不好,後期改動就會非常大。比如JDK的迭代器只支援正向遍歷,如果想實現其他遍歷方式只能通過新增輔助類實現。