1. 程式人生 > >設計模式之九:迭代器模式(Iterator Pattern)

設計模式之九:迭代器模式(Iterator Pattern)

GOF 在《設計模式》:提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露該物件的內部表示。

迭代器模式 是物件行為模式。

聚合:是指一組物件的組合結構,比如:java 中的集合,陣列等。
思想:迭代模式的關鍵思想就是把聚合物件的遍歷個訪問從聚合物件中分離出來,放入單獨的迭代器中。功能:以不同的方式遍歷聚合物件,比如向前、向後等。          對同一物件進行多個遍歷。          以不同的遍歷策略來遍歷聚合物件,比如是否需要過濾等。         多太迭代:為不同的聚合結構提供統一的迭代介面。

Iterator:迭代器介面。定義訪問和遍歷元素的介面。

ConcreteIterator:具體的迭代器實現物件。實現對聚合物件的遍歷,並跟蹤遍歷時的當前位置。

Aggregate:聚合物件。定義建立相應迭代器物件的介面。

ConcreteAggregate:具體的聚合物件。實現建立相應的迭代器物件。

/**
 * 迭代介面,定義訪問和遍歷元素的操作
 */
public interface Iterator<T> {

          /**
           * 移動到聚合物件的第一個位置
           */
          public void first();
          /**
           * 移動到聚合的下一個位置
           */
          public void next();
          /**
           * 判斷是否已經移動到聚合物件的最後一個位置
           * @return
           */

          public boolean isLast();
          /**
           * 獲取迭代的當前元素
           * @return 迭代的當前元素
           */
          public T currentItem();
}

/**
 * 具體的迭代器實現物件,不同的聚合物件相應的迭代實現不一樣
 */
public class  ConcreteIterator<T> implements Iterator<T> {

           /**
            * 持有被迭代的具體的聚合物件
            */

           private ConcreteAggregate<T> aggregate;
           /**
            * 內部索引,記錄當前迭代到得索引位置
            * -1表示剛開始的時候,迭代器指向聚合物件第一個物件之前
            */
           private int index = -1;
 
           public ConcreteIterator(ConcreteAggregate<T> aggregate){
                      this.aggregate = aggregate;
           }
           @Override
           public void first() {
                      index = 0;
           }

           @Override
           public void next() {
                     if(index this.aggregate.size()){
                                  index index + 1;
                     }
           }

           @Override
           public boolean isLast() {
                     if(index == this.aggregate.size()){
                                return true;
                     }
                     return false;
           }

           @Override
           public T currentItem() {
                     return this.aggregate.get(index);
           }

}
/**
 * 聚合物件的介面,定義建立相應迭代器物件的介面
 */

public abstract class Aggregate<T> {

         /**
          * 工廠方法,建立相應迭代器物件的介面
          * @param <T>
          * @return 相應迭代器物件的介面
          */
         public abstract Iterator<T> createIterator();
}

/**
 * 具體的聚合物件,實現建立相應迭代器物件的功能
 */
public class ConcreteAggregate<T> extends Aggregate<T> {

          /**
           * 聚合物件的具體內容
           */
          private T[] ss null;
          public ConcreteAggregate(T[] ss) {
                   super();
                   this.ss = ss;
          }

          @Override
          public Iterator<T> createIterator() {
                    //實現建立Iterator的工廠方法
                    return new ConcreteIterator<T>(this);
          }
          /**
           * 獲取索引所對應的元素
           * @param index 索引
           * @return 索引所對應的元素
           */
          public T get(int index){
                    T retObj = null;
                    if(index < ss.length){
                                retObj = ss[index];
                     }
                     return retObj;
         }
         /**
          * 獲取聚合物件的大小
          * @return 聚合物件的大小
          */
        public int size(){
                  return this.ss.length;
        }

}

public class Client {

          public static void main(String[] args) {
                    Long[] names = {100L, 120L, 130L};
                    Aggregate<Long> aggregate = new ConcreteAggregate<Long>(names);
                   Iterator<Long> it = aggregate.createIterator();
                   it.first();
                   while(!it.isLast()){
                           Long obj = it.currentItem();
                           System.out.println("the obj==" + obj);
                           it.next();
                   }
          }

}

迭代器模式的優點有:

  • 簡化了遍歷方式,對於物件集合的遍歷,還是比較麻煩的,對於陣列或者有序列表,我們尚可以通過遊標來取得,但使用者需要在對集合瞭解很清楚的前提下,自行遍歷物件,但是對於hash表來說,使用者遍歷起來就比較麻煩了。而引入了迭代器方法後,使用者用起來就簡單的多了。
  • 可以提供多種遍歷方式,比如說對有序列表,我們可以根據需要提供正序遍歷,倒序遍歷兩種迭代器,使用者用起來只需要得到我們實現好的迭代器,就可以方便的對集合進行遍歷了。
  • 封裝性良好,使用者只需要得到迭代器就可以遍歷,而對於遍歷演算法則不用去關心。

迭代器模式的缺點:

  • 對於比較簡單的遍歷(像陣列或者有序列表),使用迭代器方式遍歷較為繁瑣,大家可能都有感覺,像ArrayList,我們寧可願意使用for迴圈和get方法來遍歷集合。