熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java設計模式之迭代器模式

2022-06-13   來源: Java高級技術 
引言

  迭代這個名詞對於熟悉Java的人來說絕對不陌生我們常常使用JDK提供的迭代接口進行java collection的遍歷

Iterator it = erator();
while(ithasNext()){
 //using itnext();do some businesss logic
}
  而這就是關於迭代器模式應用很好的例子

   定義與結構

  迭代器(Iterator)模式又叫做游標(Cursor)模式GOF給出的定義為提供一種方法訪問一個容器(container)對象中各個元素而又不需暴露該對象的內部細節

  從定義可見迭代器模式是為容器而生很明顯對容器對象的訪問必然涉及到遍歷算法你可以一股腦的將遍歷方法塞到容器對象中去或者根本不去提供什麼遍歷算法讓使用容器的人自己去實現去吧這兩種情況好像都能夠解決問題

  然而在前一種情況容器承受了過多的功能它不僅要負責自己容器內的元素維護(添加刪除等等)而且還要提供遍歷自身的接口而且由於遍歷狀態保存的問題不能對同一個容器對象同時進行多個遍歷第二種方式倒是省事卻又將容器的內部細節暴露無遺

  而迭代器模式的出現很好的解決了上面兩種情況的弊端先來看下迭代器模式的真面目吧

  迭代器模式由以下角色組成

  ) 迭代器角色(Iterator)迭代器角色負責定義訪問和遍歷元素的接口

  ) 具體迭代器角色(Concrete Iterator)具體迭代器角色要實現迭代器接口並要記錄遍歷中的當前位置

  ) 容器角色(Container)容器角色負責提供創建具體迭代器角色的接口

  ) 具體容器角色(Concrete Container)具體容器角色實現創建具體迭代器角色的接口——這個具體迭代器角色於該容器的結構相關

  迭代器模式的類圖如下


  從結構上可以看出迭代器模式在客戶與容器之間加入了迭代器角色迭代器角色的加入就可以很好的避免容器內部細節的暴露而且也使得設計符號單一職責原則

  注意在迭代器模式中具體迭代器角色和具體容器角色是耦合在一起的——遍歷算法是與容器的內部細節緊密相關的為了使客戶程序從與具體迭代器角色耦合的困境中脫離出來避免具體迭代器角色的更換給客戶程序帶來的修改迭代器模式抽象了具體迭代器角色使得客戶程序更具一般性和重用性這被稱為多態迭代



   舉例

  由於迭代器模式本身的規定比較松散所以具體實現也就五花八門我們在此僅舉一例根本不能將實現方式一一呈現因此在舉例前我們先來列舉下迭代器模式的實現方式

  .迭代器角色定義了遍歷的接口但是沒有規定由誰來控制迭代在Java collection的應用中是由客戶程序來控制遍歷的進程被稱為外部迭代器還有一種實現方式便是由迭代器自身來控制迭代被稱為內部迭代器外部迭代器要比內部迭代器靈活強大而且內部迭代器在java語言環境中可用性很弱

  .在迭代器模式中沒有規定誰來實現遍歷算法好像理所當然的要在迭代器角色中實現因為既便於一個容器上使用不同的遍歷算法也便於將一種遍歷算法應用於不同的容器但是這樣就破壞掉了容器的封裝——容器角色就要公開自己的私有屬性在java中便意味著向其他類公開了自己的私有屬性

  那我們把它放到容器角色裡來實現好了這樣迭代器角色就被架空為僅僅存放一個遍歷當前位置的功能但是遍歷算法便和特定的容器緊緊綁在一起了

  而在Java Collection的應用中提供的具體迭代器角色是定義在容器角色中的內部類這樣便保護了容器的封裝但是同時容器也提供了遍歷算法接口你可以擴展自己的迭代器

  好了我們來看下Java Collection中的迭代器是怎麼實現的吧

//迭代器角色僅僅定義了遍歷接口

public interface Iterator {
 boolean hasNext();
 Object next();
 void remove();
}

//容器角色這裡以List為例它也僅僅是一個接口就不羅列出來了
//具體容器角色便是實現了List接口的ArrayList等類為了突出重點這裡指羅列和迭代器相關的內容
//具體迭代器角色它是以內部類的形式出來的AbstractList是為了將各個具體容器角色的公共部分提取出來而存在的

public abstract class AbstractList extends AbstractCollection implements List {
……
//這個便是負責創建具體迭代器角色的工廠方法
public Iterator iterator() {
 return new Itr();
}

//作為內部類的具體迭代器角色

private class Itr implements Iterator {
 int cursor = ;
 int lastRet = ;
 int expectedModCount = modCount;

 public boolean hasNext() {
  return cursor != size();
 }

 public Object next() {
  checkForComodification();
  try {
   Object next = get(cursor);
   lastRet = cursor++;
   return next;
  } catch(IndexOutOfBoundsException e) {
   checkForComodification();
   throw new NoSuchElementException();
  }
 }

 public void remove() {
  if (lastRet == )
   throw new IllegalStateException();
   checkForComodification();

  try {
   AbstractListthisremove(lastRet);
   if (lastRet < cursor)
    cursor;
   lastRet = ;
   expectedModCount = modCount;
  } catch(IndexOutOfBoundsException e) {
   throw new ConcurrentModificationException();
  }
 }

 final void checkForComodification() {
  if (modCount != expectedModCount)
   throw new ConcurrentModificationException();
 }
}

  至於迭代器模式的使用正如引言中所列那樣客戶程序要先得到具體容器角色然後再通過具體容器角色得到具體迭代器角色這樣便可以使用具體迭代器角色來遍歷容器了……



   實現自己的迭代器

  在實現自己的迭代器的時候一般要操作的容器有支持的接口才可以而且我們還要注意以下問題

  在迭代器遍歷的過程中通過該迭代器進行容器元素的增減操作是否安全呢?

  在容器中存在復合對象的情況迭代器怎樣才能支持深層遍歷和多種遍歷呢?

  以上兩個問題對於不同結構的容器角色各不相同值得考慮

   適用情況

  由上面的講述我們可以看出迭代器模式給容器的應用帶來以下好處

  ) 支持以不同的方式遍歷一個容器角色根據實現方式的不同效果上會有差別

  ) 簡化了容器的接口但是在java Collection中為了提高可擴展性容器還是提供了遍歷的接口

  ) 對同一個容器對象可以同時進行多個遍歷因為遍歷狀態是保存在每一個迭代器對象中的

  由此也能得出迭代器模式的適用范圍

  ) 訪問一個容器對象的內容而無需暴露它的內部表示

  ) 支持對容器對象的多種遍歷

  ) 為遍歷不同的容器結構提供一個統一的接口(多態迭代)

   總結

  迭代器模式在我們的應用中很廣泛希望本文能幫助你理解它如有不對之處還請不吝指正


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27339.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.