設計模式 ( 十四 ) 迭代器模式Iterator(對象行為型)

1.概述

類中的面向對象編程封裝應用邏輯。類,就是實例化的對象,每個單獨的對象都有一個特定的身份和狀態。單獨的對象是一種組織代碼的有用方法,但通常你會處理一組對象或者集合。

集合不一定是均一的。圖形用戶界面框架中的 Window 對象可以收集任意數量的控制對象 - Menu、Slider 和 Button。并且,集合的實現可以有多種方式:PHP 數字是一個集合,但也是一個散列表,一個鏈接列表,一個堆棧以及隊列。

例子1:電視遙控器的頻道遍歷

2.png

2.問

如何操縱任意的對象集合? 

如一個列表(List)或者一個集合(Set),我們又如何提供一種方法來讓別人可以訪問它的元素,而又不需要暴露它的內部結構?

3.解決方案

迭代器模式:使用迭代器模式來提供對聚合對象的統一存取,即提供一個外部的迭代器來對聚合對象進行訪問和遍歷 , 而又不需暴露該對象的內部結構。又叫做游標(Cursor)模式 。
你可能沒有意識到這一點,但你每天都在使用迭代器模式 。
如在PHP開發中,它潛藏在 PHP 的數組類型和各種數組操作函數中。(其實,給你一些固有類的數組的組合和一群用這些固有類工作的可變函數,你將不得不使用這些數組來處理對象集合。這是在 PHP 中的本地數組迭代:

$test  =  array(‘one’,  ‘two’,  ‘three’);  
$output  =  ‘’; reset($test);   
do  {  
$output  .=  current($test);  
}  while  (next($test));  
echo  $output;  //  produces  ‘onetwothree’

        reset() 函數將迭代重新轉到數組的開始;current() 返回當前元素的值;next() 則前進至數組中的下一個元素并返回新的 current() 值。當你超出數組的最后一個元素時,next() 返回 false。使用這些迭代方法,PHP 數組的內部實現就與你不相關了。

        迭代器結合了封裝和多態的面向對象程序設計原理。使用迭代器,你可以對集合中的對象進行操作,而無需專門了解集合如何顯現或者集合包含什么(對象的種類)。迭代器提供了不同固定迭代實現的統一接口,它完全包含了如何操縱特定集合的詳細信息,包括顯示哪些項(過濾)及其顯示順序(排序)。

4.適用性

迭代器模式可用來:

? 訪問一個聚合對象的內容而無需暴露它的內部表示。
? 需要為聚合對象提供多種遍歷方式。
? 為遍歷不同的聚合結構提供一個統一的接口 (即, 支持多態迭代)

5.結構

1.jpg

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

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

6.模式的組成

抽象迭代器(Iterator): 迭代器定義訪問和遍歷元素的接口。
具體迭代器(ConcreteIterator):  具體迭代器實現迭代器Iterator接口。對該聚合遍歷時跟蹤當前位置。
抽象聚合類(Aggregate): 聚合定義創建相應迭代器對象的接口。
具體聚合類(ConcreteAggregate): 體聚合實現創建相應迭代器的接口,該操作返回ConcreteIterator的一個適當的實例。

7.效果

?迭代器模式的作用:

1 ) 它支持以不同的方式遍歷一個聚合對象 : 復雜的聚合可用多種方式進行遍歷。迭代器模式使得改變遍歷算法變得很容易 : 僅需用一個不同的迭代器的實例代替原先的實例即可。你也可以自己定義迭代器的子類以支持新的遍歷。
2) 迭代器簡化了聚合的接口 有了迭代器的遍歷接口,聚合本身就不再需要類似的遍歷接口了。這樣就簡化了聚合的接口。
3) 在同一個聚合上可以有多個遍歷 每個迭代器保持它自己的遍歷狀態。因此你可以同時進行多個遍歷。

4)在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼,滿足“開閉原則”的要求。

迭代器模式的缺點

由于迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性。

8.實現

我們直接實現spl的iterator:

<?php  
  
/** 
 * 具體迭代器(ConcreteIterator):  具體迭代器實現迭代器Iterator接口。對該聚合遍歷時跟蹤當前位置。 
 */  
class  ConcreteIterator implements  Iterator {  
    protected $_key;  
    protected $_collection;  
    public function __construct($collection){  
        $this->_collection = $collection;  
        $this->_key = 0;  
    }  
    public function rewind(){  
        $this->_key = 0;  
    }  
    public function valid(){  
  
        return isset($this->_collection[$this->_key]);  
    }  
    public function key(){  
        return $this->_key;  
    }  
    public function current(){  
        return $this->_collection[$this->_key];  
    }  
    public function next(){  
        return ++$this->_key;  
    }  
  
}  
  
/** 
 * 具體聚合類(ConcreteAggregate):  
 */  
class ConcreteAggregate implements IteratorAggregate{  
    protected $_arr;  
    public function __construct($array){  
        $this->_arr = $array;  
    }  
  
    public function getIterator(){  
        return new    ConcreteIterator($this->_arr);  
    }  
}  
  
$_collectionay = array(1,2,3,3,4);  
$it = new ConcreteIterator($_collectionay);  
foreach($it as $key=>$value){  
    echo $key.':'.$value.'<br/>';  
}

9.與其他相關模式

Composite :迭代器常被應用到象復合這樣的遞歸結構上。
Factory Method:多態迭代器靠Factory Method來例化適當的迭代器子類。
Memento:常與迭代器模式一起使用。迭代器可使用一個 Memento來捕獲一個迭代的狀態。迭代器在其內部存儲Memento。

10.總結與分析

1)聚合是一個管理和組織數據對象的數據結構。

2)聚合對象主要擁有兩個職責:一是存儲內部數據;二是遍歷內部數據。

3)存儲數據是聚合對象最基本的職責。

4)將遍歷聚合對象中數據的行為提取出來,封裝到一個迭代器中,通過專門的迭代器來遍歷聚合對象的內部數據,這就是迭代器模式的本質。迭代器模式是“單一職責原則”的完美體現。

轉自:http://blog.csdn.net/hguisu/article/details/7552841

原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/2915

(0)
s19930811s19930811
上一篇 2015-07-16 22:26
下一篇 2015-07-19 22:11

相關推薦

  • 軟件包管理器之二——YUM介紹及使用

    一、前言     之前我們介紹了RPM的應用(詳細請查看http://www.www58058.com/archives/6383),發覺RPM安裝軟件有一個很繁瑣的問題,那就是包與包之間的依賴關系,如果想正常安裝和使用軟件程序,就必須根據要求一步一步的解決軟件之間的依賴關系。那么如果程序使用的包很多,將會很消耗使用人…

    Linux干貨 2015-07-21
  • 文件查找命令之locate、find簡析

    文件查找命令之locate、find簡析    在工作中經常會在文件系統上查找符合條件的文件,今天學習了文件查找命令,在此簡析locate和find兩個文件查找工具。 一、雜項知識整理 1、find的選項-user的實質是通過UID查找,如果兩個用戶的UID相同,其會顯示兩個用戶的所有符合條件的文件。 2、查找時-name "*…

    Linux干貨 2016-08-15
  • 整型、浮點型在內存中的存儲方式

      在學習C語言的過程中,有時候會想,數據到底是以什么樣的方式在內存中存儲的呢?經過一段時間的查閱資料,小編終于整理了一些…… 以VC6.0編譯器為測試環境(int型為4Byte) 先簡介一下大小端模式,具體資料可參考 http://blog.csdn.net/ce123_zhouwei/article/details/6971544  …

    Linux干貨 2016-01-14
  • 基于NFS實現WordPress

    實驗內容: (1)主機IP nfs server IP :192.168.29.120 nfs server IP: 192.168.29.110 (2)要求 nfs server共享/data/web/ 、/data/mysql 兩個目錄 nfs client掛載nfs server共享的/data/web/的文件系統至/var/www/html;部署wo…

    2017-06-13
  • 持續交付的Mesos與Docker導入篇

    變革這個詞在當今的數字化時代司空見慣,IT技術每過一段時間就會有一起革新,從WEB2.0、虛擬化、云計算、大數據、微架構、DevOps再到今天的容器Docker與Mesos。 Docker的出現方便了應用的測試、部署、與升級,其將各種應用程序和它們所依賴的運行環境打包成標準的Container/Image,進而發布到不同的平臺上運行。Docker的輕量級、快…

    Linux干貨 2016-07-10
  • 馬哥教育網絡班19期+第七周課程練習

    1、創建一個10G分區,并格式為ext4文件系統;   (1) 要求其block大小為2048, 預留空間百分比為2, 卷標為MYDATA, 默認掛載屬性包含acl;         mke2fs -b 2048 -m 2 -L 'MYDATA' -o defau…

    Linux干貨 2016-06-21
欧美性久久久久