《PHP設(shè)計(jì)模式介紹》第十三章 適配器模式(2)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第十二章 裝飾器模式若你從事過(guò)面向?qū)ο蟮膒hp開(kāi)發(fā),即使很短的時(shí)間或者僅僅通過(guò)本書(shū)了解了一些,你會(huì)知道,你可以 通過(guò)繼承改變或者增加一個(gè)類的功能,這是所有面向?qū)ο笳Z(yǔ)言的一個(gè)基本特性。如果已經(jīng)存在的一個(gè)php
當(dāng)?shù)玫降诙姹綡wLib的時(shí)候,你如何使它在第一版本HwLib的實(shí)例中體現(xiàn)?
| class HwLibV2ToV1Adapter { var $libv2; function HwLibV2ToV1Adapter (&$libv2) { $this->libv2 =& $libv2; } function hello() { return $this->libv2->greet(); } function world() { return $this->libv2->world(); } } |
HwLibV2ToV1Adapter::hello()方法代表了$libv2對(duì)象的greet()方法。
接著,你該如何在程序中使用它?
| class AdapterTestCase extends UnitTestCase { function TestOriginalAppWithAdapter() { $lib =& new HwLibV2ToV1Adapter(new HwLib); $this->assertEqual( ‘Greetings and Salutations World!’ ,$lib->hello().$lib->world()); } } |
剛才的程序測(cè)試和現(xiàn)在的程序代碼都有一定程度的脆弱性。有沒(méi)有方法在長(zhǎng)久的使用中讓它們都更易于維護(hù)呢?當(dāng)然是有的!
回憶一下(第三章)Factory是如何提供一個(gè)更靈活的方法來(lái)創(chuàng)建類的實(shí)例的。為了更好地在將來(lái)檢驗(yàn)這些代碼,就從一個(gè)簡(jiǎn)單的Factory函數(shù)開(kāi)始:
| function &HwLibInstance() { return new HwLib; } |
為了測(cè)試Factory,直接調(diào)用它而不創(chuàng)建它的實(shí)例:
| class AdapterTestCase extends UnitTestCase { function TestAppWithFactory() { $lib =& HwLibInstance(); $this->assertWantedPattern( ‘/\w World!$/’ ,$lib->hello().$lib->world()); } } |
有兩個(gè)方面需要注意:Factory創(chuàng)建了對(duì)象,而用于確認(rèn)的assertEqual()函數(shù)被修改為更靈活的assertWantedPattern()。你現(xiàn)在可以用一個(gè)正則表達(dá)式來(lái)捕獲你在庫(kù)中所要查找的“核心”,但可能會(huì)使這個(gè)測(cè)試本身變得脆弱。
接下來(lái),升級(jí)HwLib庫(kù)。當(dāng)安裝了HwLib第二版,你就可以修改HwLibInstance()函數(shù)來(lái)適應(yīng)新的版本。
| function &HwLibInstance($ver=false) { switch ($ver) { case ‘V2’: return new HwLib; default: return new HwLibV2ToV1Adapter(new HwLib); } } |
現(xiàn)在重新運(yùn)行AdapterTestCase。測(cè)試通過(guò)!(綠色進(jìn)度條正常。)因?yàn)樵嫉某绦驔](méi)有傳遞一個(gè)參數(shù),HwLibInstance會(huì)默認(rèn)返回封裝在HwLibV2toV1Adapter中的HwLib的一個(gè)實(shí)例。盡管如此,如果你編寫(xiě)了新的代碼,你可以傳遞進(jìn)一個(gè)“V2”的參數(shù)讓這個(gè)函數(shù)自動(dòng)選擇HwLib的新版本而不用去調(diào)整它。
以后,如果你選擇升級(jí)HwLib的第三版,應(yīng)該將Factory做如下的調(diào)整:
| function &HwLibInstance($ver=false) { switch ($ver) { case ‘V3’: return new HwLib; case ‘V2’: return new HwLibV3ToV2Adapter(new HwLib); default: return new HwLibV2ToV1Adapter( new HwLibV3ToV2Adapter(new HwLib)); } } |
總結(jié)
如例中代碼所示,你可以運(yùn)用適配器(Adapter)模式來(lái)避免因外部庫(kù)改變所帶來(lái)的不便——倘若向上兼容。作為某個(gè)庫(kù)的開(kāi)發(fā)者,你應(yīng)該獨(dú)立編寫(xiě)適配器,使你的用戶更簡(jiǎn)便地使用新版本的庫(kù),而不用去修改他們現(xiàn)有的全部代碼。
GoF書(shū)中提出的適配器(Adapter)模式更傾向于運(yùn)用繼承而不是組成。這在強(qiáng)類型語(yǔ)言中是有利的,因?yàn)檫m配器(Adapter)事實(shí)上是一個(gè)目標(biāo)類的子類,因而能更好地與類中方法相結(jié)合。
下面是HwLib適配器運(yùn)用繼承的范例:
class HwLibGofAdapter extends HwLib { // extending version 2.0
function hello() {
return parent::greet();
}
}
world()方法沒(méi)有在類中提到,因?yàn)檫\(yùn)用了繼承,它已經(jīng)是子類的一部分。
class AdapterTestCase extends UnitTestCase {
function TestHwLibGofAdapter() {
$lib =& new HwLibGofAdapter;
$this->assertEqual(
‘Greetings and Salutations World!’
,$lib->hello().$lib->world());
}
}
為了更好的靈活性,我個(gè)人比較傾向于組成的方法(特別是在結(jié)合了依賴性倒置的情況下);盡管如此,繼承的方法提供兩種版本的接口,或許在你的實(shí)際運(yùn)用中反而是一個(gè)提高靈活性的關(guān)鍵。
?注:依賴性倒置原理
依賴性倒置原理(首先在http://www.objectmentor.com/resources/articles/dip.pdf中由Robert C. Martin提出)是一個(gè)面向?qū)ο缶幊痰臏?zhǔn)則,它表明:高層次的模塊不應(yīng)該依賴于低層次的模塊,而應(yīng)依賴于抽取。一個(gè)簡(jiǎn)單的與適配器(Adapter)模式相結(jié)合的依賴性倒置原理范例可以在以下地址中找到:
http://www.phplondon.org/wiki/DependencyInversion
適配器模式的重點(diǎn)是改變一個(gè)單獨(dú)類的API。有一個(gè)與之相關(guān)的設(shè)計(jì)模式(本書(shū)中沒(méi)有涵蓋),稱作正面(Facade)模式。正面(Facade)的目的是給由許多對(duì)象構(gòu)成的整個(gè)子系統(tǒng),提供更為簡(jiǎn)潔的接口——反過(guò)來(lái)就是封裝一個(gè)單獨(dú)類——可能是一個(gè)值得研究的模式,如果你正設(shè)法把你的代碼與第三方庫(kù)隔離開(kāi)來(lái)的話。
分享:《PHP設(shè)計(jì)模式介紹》第十一章 代理模式因?yàn)槟硞(gè)對(duì)象消耗太多資源,而且你的代碼并不是每個(gè)邏輯路徑都需要此對(duì)象, 你曾有過(guò)延遲創(chuàng)建對(duì)象的想法嗎 ( if和else就是不同的兩條邏輯路徑) ? 你有想過(guò)限制訪問(wèn)某個(gè)對(duì)象,也就是說(shuō),提供一組方法
- 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采集文章中的圖片獲取替換到本地
- 相關(guān)鏈接:
- 教程說(shuō)明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第十三章 適配器模式(2)
。