日韩天天综合网_野战两个奶头被亲到高潮_亚洲日韩欧美精品综合_av女人天堂污污污_视频一区**字幕无弹窗_国产亚洲欧美小视频_国内性爱精品在线免费视频_国产一级电影在线播放_日韩欧美内地福利_亚洲一二三不卡片区

《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式(4)_PHP教程

編輯Tag賺U幣
教程Tag:暫無(wú)Tag,歡迎添加,賺取U幣!

推薦:《PHP設(shè)計(jì)模式介紹》第七章 策略模式
在編寫(xiě)面向?qū)ο蟮拇a的時(shí),有些時(shí)候你需要一個(gè)能夠自己根據(jù)不同的條件來(lái)引入不同的操作對(duì)象實(shí)例。例如,一個(gè)菜單功能能夠根據(jù)用戶的“皮膚”首選項(xiàng)來(lái)決定是否采用水平的還是垂直的排

class LibraryReleasedExternalIterator {
protected $collection; protected $sorted_keys; protected $key=-1;
function __construct($collection) {
$this->collection = $collection;
$sort_funct = create_function(
í $a,$b,$c=false’,
í畇tatic $collection;
if ($c) {
$collection = $c;
return;
}
return ($collection->get($a)->year -
$collection->get($b)->year);’);
$sort_funct(null,null,$this->collection);
$this->sorted_keys = $this->collection->keys();
usort($this->sorted_keys, $sort_funct);
}
function next() {
if ( $this->key >= $this->collection->count()) {
return false;
} else {
return $this->collection->get($this->sorted_keys[$this->key]);
}
}
}


其中,關(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 {
protected $lib;
function setup() {
$this->lib = new ForeachableLibrary;
$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);
}
}

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 {
protected $iterator;
function current() {
return $this->iterator->current();
}
function next() {
return $this->iterator->next();
}
function key() {
return $this->iterator->key();
}
function valid() {
return $this->iterator->valid();
}
function rewind() {
$this->iterator =
new StandardLibraryIterator($this->collection);
$this->iterator->rewind();
}
}

擴(kuò)展庫(kù)加入集合處理方法。并添加 SPL 方法,這些方法代表了 $iterator 屬性,在 rewind() 中創(chuàng)建。以下是StandardLibraryIterator 的代碼。


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;
}
function rewind() {
$this->valid = (false !== reset($this->collection));
}
}

該代碼看起來(lái)很熟悉:實(shí)際上,這來(lái)自于 5 個(gè) SPL 函數(shù)ForeachableLibrary 類。

測(cè)試類

現(xiàn)在,代碼更加復(fù)雜了,但是其如何支持其它迭代器類型?添加一個(gè)關(guān)于“發(fā)行版”迭代器的測(cè)試,來(lái)查看這種設(shè)計(jì)的其它迭代器如何工作。

class PolySplIteratorTestCase extends UnitTestCase {
// ...
function TestReleasedForeach() {
$this->lib->add(new Media(‘second’, 1999));
$this->lib->add(new Media(‘first’, 1989));
$output = array();
$this->lib->iteratorType(‘Released’);
foreach($this->lib as $item) {
$output[] = $item->name .’-’. $item->year;
}
$this->assertEqual(
‘first-1989 second-1999 name1-2000 name3-2001 name2-2002’
,implode(‘ ‘,$output));
}
}

上面的測(cè)試用例看起來(lái)也很熟悉,因?yàn)槠浞浅n愃朴谇耙粋(gè)“發(fā)行版”迭代器,但是

使用了 foreach 控制結(jié)構(gòu)進(jìn)行循環(huán)。

class PolymorphicForeachableLibrary
extends Library implements Iterator {
protected $iterator_type;
protected $iterator;
function __construct() {
$this->iteratorType();
}
function iteratorType($type=false) {
switch(strtolower($type)) {
case ‘released’:
$this->iterator_type = ‘ReleasedLibraryIterator’;
break;
default:
$this->iterator_type = ‘StandardLibraryIterator’;
}
$this->rewind();
}
// ...
function rewind() {
$type = $this->iterator_type;
$this->iterator = new $type($this->collection);
$this->iterator->rewind();
}
}


新的 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ù)連接就是這

共4頁(yè)上一頁(yè)1234下一頁(yè)
來(lái)源:模板無(wú)憂//所屬分類:PHP教程/更新時(shí)間:2008-08-22
相關(guān)PHP教程