你可以用以下的代碼開(kāi)始:
class CacheWriter { function store($file_handle, $var) { die(‘a(chǎn)bstract class-implement in concrete CacheWriter’); } }
這個(gè)就是PHP4版本的接口。(你可以從這個(gè)類(lèi)進(jìn)行繼承來(lái)保證你使用的是子類(lèi),這樣做的話只是增加了一些系統(tǒng)的負(fù)載。尤其在基類(lèi)CacheWriter是在另外一個(gè)文件定義的時(shí)候。負(fù)載增加得稍微多一些。)
基類(lèi)CacheWriter 調(diào)用了store() 方式函數(shù)來(lái)引入文件處理資源和參數(shù)來(lái)進(jìn)行存儲(chǔ)。每一個(gè)實(shí)際的類(lèi)都從執(zhí)行store()函數(shù), 但是不同的實(shí)例在store()函數(shù)里面使用的運(yùn)算法則是不一樣的,以便不同的數(shù)據(jù)類(lèi)型生成的$cached_content是不同的。每一個(gè)運(yùn)算法則被當(dāng)作一個(gè)單獨(dú)的類(lèi)來(lái)運(yùn)行。
前面的例子中的代碼被替換為:
132
The Strategy Pattern
class VarCache { // ... function _getTemplate() { $template = ‘<?php $cached_content = ‘; switch ($this->_type) { case ‘string’: $template .= “‘%s’;”; break; } // ... } function set($value) { $file_handle = fopen($this->_name.’.php’, ‘w’); switch ($this->_type) { case ‘string’: $content = sprintf($this->_getTemplate() ,str_replace(“‘“,”\\’”,$value)); break; // ... } fwrite($file_handle, $content); fclose($file_handle); } }
針對(duì)每一個(gè)緩存的數(shù)據(jù)來(lái)型,你需要實(shí)例出相對(duì)應(yīng)的_getTemplate() 和
set() 方式函數(shù)到相對(duì)應(yīng)的類(lèi)當(dāng)中。這里是StringCacheWriter:
class StringCacheWriter /* implements CacheWriter */ { function store($file_handle, $string) { $content = sprintf( “<?php\n\$cached_content = ‘%s’;” ,str_replace(“‘“,”\\’”,$string)); fwrite($file_handle, $contents); } }
(因?yàn)镻HP 4不支持接口的使用,這里接口只是用注釋來(lái)簡(jiǎn)單描述一下。)
這里我們得到另外一個(gè)運(yùn)算法則存儲(chǔ)“策略”。
class NumericCacheWriter /* implements CacheWriter */ { function store($file_handle, $numeric) { $content = sprintf(“<?php\n\$cached_content = %s;” ,(double)$numeric);
The Strategy Pattern 133
fwrite($file_handle, $content); } } class SerializingCacheWriter /* implements CacheWriter */ { function store($file_handle, $var) { $content = sprintf( “<?php\n\$cached_content = unserialize(stripslashes(‘%s’));” ,addslashes(serialize($var))); fwrite($file_handle, $content); } }
通過(guò)把運(yùn)算法則封裝到交互的類(lèi)中(同樣的API,多形性),你現(xiàn)在可以回過(guò)頭來(lái)通過(guò)策略設(shè)計(jì)模式重新執(zhí)行VarCache()類(lèi)。這個(gè)時(shí)候經(jīng)過(guò)條件分解但是與原來(lái)非常類(lèi)似的代碼可以繼續(xù)運(yùn)行了。
class VarCache { var $_name; var $_type; function VarCache($name, $type=’serialize’) { $this->_name = ‘cache/’.$name; switch (strtolower($type)) { case ‘string’: $strategy = ‘String’; break; case ‘numeric’: $strategy = ‘Numeric’; break; case ‘serialize’: default: $strategy = ‘Serializing’; } $strategy .= ‘CacheWriter’; $this->_type =& new $strategy; } function isValid() { return file_exists($this->_name.’.php’); } function get() { if ($this->isValid()) { include $this->_name.’.php’; return $cached_content; } } function set($value) { $file_handle = fopen($this->_name.’.php’, ‘w’); $this->_type->store($file_handle, $value); fclose($file_handle); } }
通過(guò)創(chuàng)建實(shí)際的CacheWriter 類(lèi)的實(shí)例并讓它幫定實(shí)際的$_type變量,你可以使用 $this->_type->store($file_handle, $value) 語(yǔ)句來(lái)寫(xiě)入緩存數(shù)據(jù)。
134
The Strategy Pattern
緩存文件的時(shí)候,我們將不再關(guān)心初始化的時(shí)候是用什么運(yùn)算法則來(lái)存儲(chǔ)數(shù)據(jù)。
下面描述了定義策略設(shè)計(jì)模式的幾個(gè)特性:一系列的運(yùn)算法則,每個(gè)運(yùn)算法則都是封裝在獨(dú)立的類(lèi)中。但是,每一個(gè)對(duì)象都是綁定到一個(gè)公共的容器對(duì)象中。并且,通過(guò)一個(gè)公共的API使用同樣的方式在進(jìn)行引用。而這個(gè)公共的API的運(yùn)行方式是與策略的選擇無(wú)關(guān)的。
評(píng)論
策略設(shè)計(jì)模式的功能是非常強(qiáng)大的 。本書(shū)到現(xiàn)在為止所說(shuō)的其它的設(shè)計(jì)模式提供的都是應(yīng)用的基礎(chǔ)模塊功能,而 策略設(shè)計(jì)模式是目前第一個(gè)擁有設(shè)計(jì)模式和項(xiàng)目的遷移里面關(guān)鍵功能的設(shè)計(jì)模式。
它可以替換掉一個(gè)對(duì)象里面編寫(xiě)復(fù)雜的部分,改變整個(gè)對(duì)象的運(yùn)行和性能,這點(diǎn)功能是非常強(qiáng)大的。另外,一個(gè)特定策略使用以后馬上就被清空了,這個(gè)使得剩下的API非常容易執(zhí)行。從根本上說(shuō),選用哪個(gè)運(yùn)算法則對(duì)于其它的代碼來(lái)說(shuō)都是透明的。
互聯(lián)網(wǎng)上有這么一個(gè)說(shuō)法“本質(zhì)上說(shuō),任何一個(gè)事情開(kāi)始的時(shí)候都像在使用策略模式!睘槭裁茨?因?yàn)檫@個(gè)設(shè)計(jì)模式有效應(yīng)用了多形性的特點(diǎn),而這個(gè)也是面向?qū)ο缶幊套顝?qiáng)大的幾個(gè)方面之一。
相關(guān)的設(shè)計(jì)模式
策略模式和其它許多設(shè)計(jì)模式比較起來(lái)是非常類(lèi)似的。策略模式和狀態(tài)模式最大的區(qū)別就是策略模式只是的條件選擇只執(zhí)行一次,而狀態(tài)模式是隨著實(shí)例參數(shù)(對(duì)象實(shí)例的狀態(tài))的改變不停地更改執(zhí)行模式。換句話說(shuō),策略模式只是在對(duì)象初始化的時(shí)候更改執(zhí)行模式,而狀態(tài)模式是根據(jù)對(duì)象實(shí)例的周期時(shí)間而動(dòng)態(tài)地改變對(duì)象實(shí)例的執(zhí)行模式。
注: 設(shè)計(jì)模式—狀態(tài) Design Pattern—State 狀態(tài)設(shè)計(jì)模式允許一個(gè)對(duì)象實(shí)例因?yàn)橐粋(gè)內(nèi)部的狀態(tài)改變而改變其執(zhí)行模式。 因此,對(duì)象實(shí)例自身可以有效地改變其類(lèi)定義。
油漆工設(shè)計(jì)模式(見(jiàn)第十二章) 在概念上正好和策略模式是相反的。借用GoF的一個(gè)推論,策略模式改變的是一個(gè)對(duì)象實(shí)例的核心的復(fù)雜操作,而油漆工設(shè)計(jì)模式改變的是一個(gè)對(duì)象實(shí)例的皮膚。
最后一個(gè)相關(guān)的設(shè)計(jì)模式是訪問(wèn)者設(shè)計(jì)模式。在策略模式里面,你創(chuàng)建一個(gè)實(shí)際的選擇的策略的對(duì)象實(shí)例然后把它綁定到一個(gè)實(shí)例參數(shù)中;在訪問(wèn)者模式里面,策略使用參數(shù)的方式進(jìn)行傳遞的。你可以想象下訪問(wèn)者設(shè)計(jì)模式,它的設(shè)計(jì)思路和策略模式正好相反。
下文:《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式
本文鏈接:http://www.95time.cn/tech/program/2008/5992.asp
出處:
責(zé)任編輯:bluehearts
上一頁(yè) php設(shè)計(jì)模式介紹之策略模式 [4] 下一頁(yè)
◎進(jìn)入論壇網(wǎng)絡(luò)編程版塊參加討論
|