《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第七章 策略模式在編寫面向?qū)ο蟮拇a的時(shí),有些時(shí)候你需要一個(gè)能夠自己根據(jù)不同的條件來(lái)引入不同的操作對(duì)象實(shí)例。例如,一個(gè)菜單功能能夠根據(jù)用戶的“皮膚”首選項(xiàng)來(lái)決定是否采用水平的還是垂直的排
類中的面向?qū)ο缶幊谭庋b應(yīng)用邏輯。類,就是實(shí)例化的對(duì)象,每個(gè)單獨(dú)的對(duì)象都有一個(gè)特定的身份和狀態(tài)。單獨(dú)的對(duì)象是一種組織代碼的有用方法,但通常你會(huì)處理一組對(duì)象或者集合。
屬性來(lái)自 SQL 查詢的一組數(shù)據(jù)就是一個(gè)集合,就像本書前面章節(jié)介紹的 Monopoly 游戲示例的對(duì)象列表。
集合不一定是均一的。圖形用戶界面框架中的 Window 對(duì)象可以收集任意數(shù)量的控制對(duì)象 - Menu、Slider 和 Button。并且,集合的實(shí)現(xiàn)可以有多種方式:PHP 數(shù)字是一個(gè)集合,但也是一個(gè)散列表,一個(gè)鏈接列表,一個(gè)堆棧以及隊(duì)列。
問題
如何操縱任意的對(duì)象集合?
解決方案
使用迭代器模式來(lái)提供對(duì)集合內(nèi)容的統(tǒng)一存取。
你可能沒有意識(shí)到這一點(diǎn),但你每天都在使用迭代器模式 - 它潛藏在 PHP 的數(shù)組類型和各種數(shù)組操作函數(shù)中。(其實(shí),給你一些固有類的數(shù)組的組合和一群用這些固有類工作的可變函數(shù),你將不得不使用這些數(shù)組來(lái)處理對(duì)象集合。這是在 PHP 中的本地?cái)?shù)組迭代:
$test = array(‘one’, ‘two’, ‘three’); $output = ‘’; reset($test); do { $output .= current($test); } while (next($test)); echo $output; // produces ‘onetwothree’ |
reset() 函數(shù)將迭代重新轉(zhuǎn)到數(shù)組的開始;current() 返回當(dāng)前元素的值;next() 則前進(jìn)至數(shù)組中的下一個(gè)元素并返回新的 current() 值。當(dāng)你超出數(shù)組的最后一個(gè)元素時(shí),next() 返回 false。使用這些迭代方法,PHP 數(shù)組的內(nèi)部實(shí)現(xiàn)就與你不相關(guān)了。迭代器結(jié)合了封裝和多態(tài)的面向?qū)ο蟪绦蛟O(shè)計(jì)原理。使用迭代器,你可以對(duì)集合中的對(duì)象進(jìn)行操作,而無(wú)需專門了解集合如何顯現(xiàn)或者集合包含什么(對(duì)象的種類)。迭代器提供了不同固定迭代實(shí)現(xiàn)的統(tǒng)一接口,它完全包含了如何操縱特定集合的詳細(xì)信息,包括顯示哪些項(xiàng)(過濾)及其顯示順序(排序)。
讓我們創(chuàng)建一個(gè)簡(jiǎn)單的對(duì)象,在數(shù)組中對(duì)它進(jìn)行操作。(盡管該示例在 PHP5 環(huán)境下,但迭代器并不特定于 PHP5。雖然添加了較多的引用操作符,本章節(jié)中的大多數(shù)示例在 PHP4 下也能夠運(yùn)行)。對(duì)象 Lendable 表示諸如電影、相冊(cè)等媒體,它作為 web 站點(diǎn)的一部分或服務(wù),允許用戶瀏覽或?qū)⑺麄兊拿襟w集合分享給其他用戶。(對(duì) 于該示例,請(qǐng)無(wú)需考慮其他方面。)讓我們開始下面對(duì) Lendable 基礎(chǔ)設(shè)計(jì)的測(cè)試。
// PHP5 class LendableTestCase extends UnitTestCase { function TestCheckout() { $item = new Lendable; $this->assertFalse($item->borrower); $item->checkout(‘John’); $this->assertEqual(‘borrowed’, $item->status); $this->assertEqual(‘John’, $item->borrower); } function TestCheckin() { $item = new Lendable; $item->checkout(‘John’); $item->checkin(); $this->assertEqual(‘library’, $item->status); $this->assertFalse($item->borrower); } } |
要實(shí)現(xiàn)這一最初測(cè)試的需求,我們來(lái)創(chuàng)建一個(gè)帶有若干公共屬性和一些方法的類,
來(lái)觸發(fā)這些屬性的值:
class Lendable { public $status = ‘library’; public $borrower = ‘’; public function checkout($borrower) { $this->status = ‘borrowed’; $this->borrower = $borrower; } public function checkin() { $this->status = ‘library’; $this->borrower = ‘’; } } |
Lendable 是一個(gè)好的,普通的開端。讓我們將它擴(kuò)展到諸如 DVD 或 CD 的磁道項(xiàng)。媒體擴(kuò)展了 Lendable,并且磁道詳細(xì)記錄了特定媒體的詳細(xì)信息,包括項(xiàng)目的名稱,發(fā)布的年份以及項(xiàng)本身的類型:
class Media extends Lendable { public $name; public $type; public $year; public function __construct($name, $year, $type=’dvd’ ) { $this->name = $name; $this->type = $type; $this->year = (int)$year; } } |
要使事情更加簡(jiǎn)單,媒體有三個(gè)公共的實(shí)例變量,Media::name,Media::year 和Media::type。構(gòu)造函數(shù)采用了兩個(gè)參數(shù),將第一個(gè)存儲(chǔ)在 $name 中,第二個(gè)存儲(chǔ)在 $year 中。構(gòu)造函數(shù)還允許可選的第三個(gè)參數(shù)來(lái)指定類型(缺省為dvd)。
給定單獨(dú)的對(duì)象來(lái)操作,你現(xiàn)在可以創(chuàng)建一個(gè)容器來(lái)包含他們:Library。類似于常用的庫(kù),Library 應(yīng)該能夠添加,刪除和計(jì)算集合中的項(xiàng)。甚至,Library 還應(yīng)該允許訪問集合(本章中的樣本代碼部分可看到示例)中的單一的項(xiàng)(對(duì)象)。
我們開始構(gòu)建 Library 的測(cè)試用例。
class LibraryTestCase extends UnitTestCase { function TestCount() { $lib = new Library; $this->assertEqual(0, $lib->count()); } } |
它是滿足這一測(cè)試的簡(jiǎn)單類:
class Library { function count() { return 0; } } |
繼續(xù)將一些有趣的功能添加到測(cè)試中:
class LibraryTestCase extends UnitTestCase { function TestCount() { /* ... */ } function TestAdd() { $lib = new Library; $lib->add(‘one’); $this->assertEqual(1, $lib->count()); } } |
實(shí)現(xiàn) add() 的簡(jiǎn)單方法是建立在 PHP 靈活數(shù)組函數(shù)的基礎(chǔ)上:你可以將項(xiàng)添加到實(shí)例變量并使用 count() 來(lái)返回集合眾項(xiàng)的數(shù)量。
class Library { protected $collection = array(); function count() { return count($this->collection); } function add($item) { $this->collection[] = $item; } } |
Library 現(xiàn)在是一個(gè)集合,但它沒有提供檢索或操縱單一數(shù)組成員的方法。
我們回到本章的重點(diǎn),迭代器設(shè)計(jì)模式的實(shí)現(xiàn)。下列 UML 類圖顯示了 GoF 迭代器模式與 Media 和 Library 類結(jié)合使用鞏固示例的方法。
分享:《PHP設(shè)計(jì)模式介紹》第六章 偽對(duì)象模式面向?qū)ο蟮木幊讨载S富多彩,部分是由于對(duì)象間的相互聯(lián)系與作用。一個(gè)單一的對(duì)象就能封裝一個(gè)復(fù)雜的子系統(tǒng),使那些很復(fù)雜的操作能夠通過一些方法的調(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)于訪問控制的和運(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ù)讀寫次數(shù),函數(shù)調(diào)用次數(shù)等(THINKphp)
- 淺談PHP 閉包特性在實(shí)際應(yīng)用中的問題
- PHP flush()與ob_flush()的區(qū)別詳解
- php selectradio和checkbox默認(rèn)選擇的實(shí)現(xiàn)方法詳解
- 服務(wù)器變量 $_SERVER 的深入解析
- PHP preg_match的匹配多國(guó)語(yǔ)言的技巧
- 解析php中的escape函數(shù)
- 新手入門:PHP網(wǎng)站開發(fā)中常見問題匯總
- 相關(guān)鏈接:
- 教程說明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式。