《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式(4)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第七章 策略模式在編寫(xiě)面向?qū)ο蟮拇a的時(shí),有些時(shí)候你需要一個(gè)能夠自己根據(jù)不同的條件來(lái)引入不同的操作對(duì)象實(shí)例。例如,一個(gè)菜單功能能夠根據(jù)用戶的“皮膚”首選項(xiàng)來(lái)決定是否采用水平的還是垂直的排
|
class LibraryReleasedExternalIterator { |
其中,關(guān)鍵是創(chuàng)建用于排序的實(shí)用程序函數(shù)。排序函數(shù)必須能夠訪問(wèn)集合,以便可以獲取對(duì)照成員。然而,因?yàn)?gener- ated 函數(shù)在 usort() 中使用,沒(méi)有將集合作為其它參數(shù)傳遞的選項(xiàng)。相反,你可以利用上述代碼塊中顯示的訣竅,在利用 usort() 調(diào)用函數(shù)之前,將引用存儲(chǔ)在函數(shù)中內(nèi)部的集合中。排序的項(xiàng)是集合的關(guān)鍵字列表。當(dāng) usort() 完成時(shí),關(guān)鍵字會(huì)按照集合中每個(gè)對(duì)象的 year 屬性的順序進(jìn)行排序。在 next() 方法中,可以通過(guò) get() 方法訪問(wèn)集合中的對(duì)象,而不是間接通過(guò) $sorted_keys 映射。如果重新調(diào)用外部版本的 GoF 風(fēng)格的迭代器,則不連續(xù)的數(shù)組或關(guān)鍵字中的字符串可能會(huì)有問(wèn)題�?梢允褂冕槍�(duì) sim- ple 外部迭代器的相同訣竅,來(lái)減少關(guān)鍵字順序不連貫的問(wèn)題。
SPL 迭代器
《迭代器設(shè)計(jì)模式和 PHP》中必須論述“標(biāo)準(zhǔn) PHP 庫(kù)”(SPL)迭代器。雖然,使用 while 循環(huán)結(jié)構(gòu)可以非常緊湊,并且也很有用,但是 PHP 代碼或許更適合數(shù)組迭代的 foreach 結(jié)構(gòu)。直接在 foreach 循環(huán)中使用集合合適嗎?這其實(shí)就是 SPL 迭代器的目標(biāo)。(盡管本章整篇都是寫(xiě) PHP5,下列 SPL 代碼只能在 PHP5 中運(yùn)行,并且僅當(dāng)在 PHP5 編譯中將 SPL 啟用。)
Fuecks 寫(xiě)過(guò)一篇文章,詳細(xì)地介紹了 SPL 和 SPL 迭代器;請(qǐng)參閱 http://www.site-
|
point.com/article/php5-standard-library。使用 SPL 是一種完全不同的實(shí)現(xiàn)迭代的方法,因此首先介紹一個(gè)新單元測(cè)試?yán)雍鸵粋(gè)新的類 ForeachableLibrary。 class SplIteratorTestCase extends UnitTestCase { |
ForeachableLibrary 是實(shí)現(xiàn) SPL 迭代器接口的集合。你必須執(zhí)行 5 個(gè)函數(shù)來(lái)創(chuàng)建 SPL 迭代器:current()、next()、key()、valid() 和 rewind()。 key() 返回集合的當(dāng)前索引。 rewind() 類似于 reset():在集合啟動(dòng)時(shí)重新啟動(dòng)迭代。
| class ForeachableLibrary extends Library implements Iterator { protected $valid; function current() { return current($this->collection); } function next() { $this->valid = (false !== next($this->collection)); } function key() { return key($this->collection); } function valid() { return $this->valid; } function rewind() { $this->valid = (false !== reset($this->collection)); } } |
這里,該代碼僅僅實(shí)現(xiàn)了處理 $collection 屬性的必需的函數(shù)。(如果你沒(méi)有實(shí)現(xiàn)所有 5 個(gè)函數(shù),并且將實(shí)現(xiàn)迭代器添加到類 definition,則 PHP 將出現(xiàn)致命錯(cuò)誤。)測(cè)試尚不成熟,因此,什么都有可能發(fā)生。存在一個(gè)問(wèn)題:事實(shí)受限于一種迭代類型 - 排序,或者 fil- tering 不可用�?梢圆扇〈胧﹣�(lái)調(diào)整這種情況?是的!應(yīng)用從策略模式中學(xué)到的知識(shí)(請(qǐng)參閱第 7 章),將 SPL 迭代器的 5 個(gè)函數(shù)作為另一個(gè)對(duì)象的示例。這是關(guān)于 PolymorphicForeachableLibrary 的測(cè)試。
| class PolySplIteratorTestCase extends UnitTestCase { protected $lib; function setup() { $this->lib = new PolymorphicForeachableLibrary; $this->lib->add(new Media(‘name1’, 2000)); $this->lib->add(new Media(‘name2’, 2002)); $this->lib->add(new Media(‘name3’, 2001)); } function TestForeach() { $output = ‘’; foreach($this->lib as $item) { $output .= $item->name; } $this->assertEqual(‘name1name2name3’, $output); } } |
這種情況與 SplIteratorTestCase 測(cè)試的唯一差別在于 $this->lib 屬性類是在 setUp() 方法中創(chuàng)建的。這意味著:這兩個(gè)類的運(yùn)行方式必須一致。PolymorphicForeachableLibrary:class PolymorphicForeachableLibrary擴(kuò)展庫(kù)
|
implements Iterator { |
| class StandardLibraryIterator { protected $valid; protected $collection; function __construct($collection) { $this->collection = $collection; } function current() { return current($this->collection); } function next() { $this->valid = (false !== next($this->collection)); } function key() { return key($this->collection); } function valid() { return $this->valid; |
測(cè)試類
現(xiàn)在,代碼更加復(fù)雜了,但是其如何支持其它迭代器類型?添加一個(gè)關(guān)于“發(fā)行版”迭代器的測(cè)試,來(lái)查看這種設(shè)計(jì)的其它迭代器如何工作。
|
class PolySplIteratorTestCase extends UnitTestCase { |
使用了 foreach 控制結(jié)構(gòu)進(jìn)行循環(huán)。
|
class PolymorphicForeachableLibrary |
新的 iteratorType() 方法使你轉(zhuǎn)變要使用的迭代器的類型。(因?yàn)榈黝愋筒⒉皇窃趯?duì)象安裝期間選中的,并且你可以在空閑時(shí)再次調(diào)用 iteratorType() 方法來(lái)選擇不同迭代器類型,所以實(shí)際上是在 State 模式執(zhí)行代碼,而不是 Strategy 模式。)
| class ReleasedLibraryIterator extends StandardLibraryIterator { function __construct($collection) { usort($collection ,create_function(‘$a,$b’,’return ($a->year - $b->year);’)); $this->collection = $collection; } } |
你可以簡(jiǎn)單地通過(guò)擴(kuò)展 StandardLibraryIterator 并覆蓋構(gòu)造函數(shù)來(lái)添加入局?jǐn)?shù)組的排序,從而實(shí)現(xiàn) ReleasedLibraryIterator。并且,通過(guò)它,你可以有一個(gè) working PolymorphicForeachableLibrary。
總結(jié)
迭代器是標(biāo)準(zhǔn)化地地處理應(yīng)用程序中對(duì)象集合的方法。這些例子是基于數(shù)組的,但是對(duì)于擁有同一個(gè)接口的非數(shù)組集合,工作起來(lái)將更加強(qiáng)大。使用 foreach 控制結(jié)構(gòu)方式的集合確實(shí)非�?帷� SPL 實(shí)現(xiàn)中最不幸的問(wèn)題是與迭代器可能存在的名稱空間沖突。有多少 PHP4 面向?qū)ο蟮拇a擁有類似于迭代器類作為庫(kù)迭代器類的基類?在一些容量中有多少 5 種必需方法的定義?可能一個(gè)更加具有深刻含義的名稱就能實(shí)現(xiàn) Foreachable。如果你選擇使用 SPL,則還應(yīng)該研究其它支持的迭代器,例如RecursiveArrayIterator 和其它眾多迭代器。
分享:《PHP設(shè)計(jì)模式介紹》第六章 偽對(duì)象模式面向?qū)ο蟮木幊讨载S富多彩,部分是由于對(duì)象間的相互聯(lián)系與作用。一個(gè)單一的對(duì)象就能封裝一個(gè)復(fù)雜的子系統(tǒng),使那些很復(fù)雜的操作能夠通過(guò)一些方法的調(diào)用而簡(jiǎn)化。(無(wú)所不在的數(shù)據(jù)庫(kù)連接就是這
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁(yè)面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問(wèn)控制的和運(yùn)算符優(yōu)先級(jí)介紹
- 關(guān)于PHP語(yǔ)言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國(guó)語(yǔ)言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
PHP教程Rss訂閱編程教程搜索
PHP教程推薦
- php無(wú)限極分類實(shí)現(xiàn)的兩種解決方法
- vim下高亮顯示php代碼
- 獲取php頁(yè)面執(zhí)行時(shí)間,數(shù)據(jù)庫(kù)讀寫(xiě)次數(shù),函數(shù)調(diào)用次數(shù)等(THINKphp)
- 淺談PHP 閉包特性在實(shí)際應(yīng)用中的問(wèn)題
- PHP flush()與ob_flush()的區(qū)別詳解
- php selectradio和checkbox默認(rèn)選擇的實(shí)現(xiàn)方法詳解
- 服務(wù)器變量 $_SERVER 的深入解析
- PHP preg_match的匹配多國(guó)語(yǔ)言的技巧
- 解析php中的escape函數(shù)
- 新手入門(mén):PHP網(wǎng)站開(kāi)發(fā)中常見(jiàn)問(wèn)題匯總
- 相關(guān)鏈接:
- 教程說(shuō)明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式(4)
。