《PHP設計模式介紹》第七章 策略模式(3)_PHP教程
推薦:《PHP設計模式介紹》第六章 偽對象模式面向?qū)ο蟮木幊讨载S富多彩,部分是由于對象間的相互聯(lián)系與作用。一個單一的對象就能封裝一個復雜的子系統(tǒng),使那些很復雜的操作能夠通過一些方法的調(diào)用而簡化。(無所不在的數(shù)據(jù)庫連接就是這
樣本代碼
從一個多重的switch 條件判斷改變到策略模式是一個條件分解實例的經(jīng)典例子。整個測試的環(huán)境沒有變化;只是VarCache類的內(nèi)部改變了。
首先我們把你想要封裝在一個獨立的類的各種情況分隔出來。就前面的例子來說,你有三種變化的情況需要進行考慮:‘string’, ‘numeric’, 和第三個‘serialize’。前面的例子中還在對象實例化的時候選擇了數(shù)據(jù)輸出的格式�;谶@個運算法則,你需要創(chuàng)建一個API來封裝它。
你可以用以下的代碼開始:
| class CacheWriter { function store($file_handle, $var) { die(‘abstract class-implement in concrete CacheWriter’); } } |
這個就是PHP4版本的接口。(你可以從這個類進行繼承來保證你使用的是子類,這樣做的話只是增加了一些系統(tǒng)的負載。尤其在基類CacheWriter是在另外一個文件定義的時候。負載增加得稍微多一些。)
基類CacheWriter 調(diào)用了store() 方式函數(shù)來引入文件處理資源和參數(shù)來進行存儲。每一個實際的類都從執(zhí)行store()函數(shù), 但是不同的實例在store()函數(shù)里面使用的運算法則是不一樣的,以便不同的數(shù)據(jù)類型生成的$cached_content是不同的。每一個運算法則被當作一個單獨的類來運行。
前面的例子中的代碼被替換為:
|
class VarCache { |
set() 方式函數(shù)到相對應的類當中。這里是StringCacheWriter:
| class StringCacheWriter /* implements CacheWriter */ { function store($file_handle, $string) { $content = sprintf( “<?php\n\$cached_content = ‘%s’;” ,str_replace(“‘“,”\\’”,$string)); fwrite($file_handle, $contents); } } |
(因為PHP 4不支持接口的使用,這里接口只是用注釋來簡單描述一下。)
這里我們得到另外一個運算法則存儲“策略”。
| 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); } } |
通過把運算法則封裝到交互的類中(同樣的API,多形性),你現(xiàn)在可以回過頭來通過策略設計模式重新執(zhí)行VarCache()類。這個時候經(jīng)過條件分解但是與原來非常類似的代碼可以繼續(xù)運行了。
|
class VarCache { |
緩存文件的時候,我們將不再關(guān)心初始化的時候是用什么運算法則來存儲數(shù)據(jù)。
下面描述了定義策略設計模式的幾個特性:一系列的運算法則,每個運算法則都是封裝在獨立的類中。但是,每一個對象都是綁定到一個公共的容器對象中。并且,通過一個公共的API使用同樣的方式在進行引用。而這個公共的API的運行方式是與策略的選擇無關(guān)的。
評論
策略設計模式的功能是非常強大的 。本書到現(xiàn)在為止所說的其它的設計模式提供的都是應用的基礎模塊功能,而 策略設計模式是目前第一個擁有設計模式和項目的遷移里面關(guān)鍵功能的設計模式。
它可以替換掉一個對象里面編寫復雜的部分,改變整個對象的運行和性能,這點功能是非常強大的。另外,一個特定策略使用以后馬上就被清空了,這個使得剩下的API非常容易執(zhí)行。從根本上說,選用哪個運算法則對于其它的代碼來說都是透明的。
互聯(lián)網(wǎng)上有這么一個說法“本質(zhì)上說,任何一個事情開始的時候都像在使用策略模式。”為什么呢?因為這個設計模式有效應用了多形性的特點,而這個也是面向?qū)ο缶幊套顝姶蟮膸讉方面之一。
相關(guān)的設計模式
策略模式和其它許多設計模式比較起來是非常類似的。策略模式和狀態(tài)模式最大的區(qū)別就是策略模式只是的條件選擇只執(zhí)行一次,而狀態(tài)模式是隨著實例參數(shù)(對象實例的狀態(tài))的改變不停地更改執(zhí)行模式。換句話說,策略模式只是在對象初始化的時候更改執(zhí)行模式,而狀態(tài)模式是根據(jù)對象實例的周期時間而動態(tài)地改變對象實例的執(zhí)行模式。
注: 設計模式—狀態(tài)
Design Pattern—State
狀態(tài)設計模式允許一個對象實例因為一個內(nèi)部的狀態(tài)改變而改變其執(zhí)行模式。 因此,對象實例自身可以有效地改變其類定義。
油漆工設計模式(見第十二章) 在概念上正好和策略模式是相反的。借用GoF的一個推論,策略模式改變的是一個對象實例的核心的復雜操作,而油漆工設計模式改變的是一個對象實例的皮膚。
最后一個相關(guān)的設計模式是訪問者設計模式。在策略模式里面,你創(chuàng)建一個實際的選擇的策略的對象實例然后把它綁定到一個實例參數(shù)中;在訪問者模式里面,策略使用參數(shù)的方式進行傳遞的。你可以想象下訪問者設計模式,它的設計思路和策略模式正好相反。
分享:《PHP設計模式介紹》第五章 注冊模式我們通常認為避免使用全局變量是一種好的選擇,因此,對象經(jīng)常被作為參數(shù)從一段代碼傳遞到另一段。但是傳遞實例的一個問題就是對象有時候不知道將要傳遞給誰——?經(jīng)過一個函數(shù)后才被傳
- 相關(guān)鏈接:
- 教程說明:
PHP教程-《PHP設計模式介紹》第七章 策略模式(3)
。