php設(shè)計模式之委托模式
委托模式是軟件設(shè)計模式中的一項基本技巧。在委托模式中,有兩個對象參與處理同一個請求,接受請求的對象將請求委托給另一個對象來處理。委托模式是一項基本技巧,許多其他的模式,如狀態(tài)模式、策略模式、訪問者模式本質(zhì)上是在更特殊的場合采用了委托模式。
動態(tài)委托的介紹:動態(tài)委托概念來自于Jakarta 字節(jié)碼工程庫 (Byte-Code Engineering Library, BCEL)。它能夠分析存在的類,并且對于接口,抽象類,甚至運行時的具體類來說,它能夠生成以字節(jié)編碼委托類。
被委托的接口/類應(yīng)該滿足如下條件:動態(tài)委托最多只能委托一個類,但是能夠代理多個接口。這個限制來自于Java的單繼承模式。一個Java類最多只有一個父類。既然生成的委托類把被委托類作為它的父類,那么指定多個被委托類是不合理的。如果沒有指定被委托類,那么缺省的父類就是Object。
下面是PHP 反射機制實現(xiàn)動態(tài)代理的代碼:
<?php class Fruit { function callFruit() { print "Generate an Apple"; } } class FruitDelegator { private $targets; function __construct() { $this->target[] = new Fruit(); } function __call($name, $args) { foreach ($this->target as $obj) { $r = new ReflectionClass($obj); if ($method = $r->getMethod($name)) { if ($method->isPublic() && !$method->isAbstract()) { return $method->invoke($obj, $args); } } } } } $obj = new FruitDelegator(); $obj->callFruit(); // 運行結(jié)果 // Generate an Apple ?>
可見,通過代理類FruitDelegator來代替Fruit類來實現(xiàn)他的方法。
同樣的,如下的代碼也是能夠運行的:
<?php class Color { function callColor() { print "Generate Red"; } } class ColorDelegator { private $targets; function addObject($obj) { $this->target[] = $obj; } function __call($name, $args) { foreach ($this->target as $obj) { $r = new ReflectionClass($obj); if ($method = $r->getMethod($name)) { if ($method->isPublic() && !$method->isAbstract()) { return $method->invoke($obj, $args); } } } } } $obj = new ColorDelegator(); $obj->addObject(new Color()); $obj->callColor(); ?>
設(shè)計了一個cd類,類中有mp3播放模式,和mp4播放模式
改進(jìn)前,使用cd類的播放模式,需要在實例化的類中去判斷選擇什么方式的播放模式
改進(jìn)后,播放模式當(dāng)做一個參數(shù)傳入playList函數(shù)中,就自動能找到對應(yīng)需要播放的方法。
一、未改進(jìn)前
<?php //使用委托模式之前,調(diào)用cd類,選擇cd播放模式是復(fù)雜的選擇過程 class cd { protected $cdInfo = array(); public function addSong($song) { $this->cdInfo[$song] = $song; } public function playMp3($song) { return $this->cdInfo[$song] . '.mp3'; } public function playMp4($song) { return $this->cdInfo[$song] . '.mp4'; } } $oldCd = new cd; $oldCd->addSong("1"); $oldCd->addSong("2"); $oldCd->addSong("3"); $type = 'mp3'; if ($type == 'mp3') { $oldCd->playMp3(); } else { $oldCd->playMp4(); }
二、通過委托模式,改進(jìn)后的cd類
<?php namespace Tools; /* 委托模式 去除核心對象中的判決和復(fù)雜功能性 */ //委托接口 interface Delegate{ public function playList($list,$song); } //mp3處理類 class mp3 implements Delegate{ public function playList($list,$song){ return $list[$song].'.mp3'; } } //mp4處理類 class mp4 implements Delegate{ public function playList($list, $song) { return $list[$song].'.mp4'; } } class cdDelegate{ protected $cdInfo = array(); public function addSong($song){ $this->cdInfo[$song] = $song; } public function play($type,$song){ $name = '\Tools\\'.$type; $obj = new $name; return $obj->playList($this->cdInfo,$song); } } $newCd = new cdDelegate(); $newCd->addSong("1"); $newCd->addSong("2"); $newCd->addSong("3"); echo $newCd->play('mp3','1');//只要傳遞參數(shù)就能知道需要選擇何種播放模式
再為大家分享一個實例:
<?php /** * 委托模式 示例 * * @create_date: 2010-01-04 */ class PlayList { var $_songs = array(); var $_object = null; function PlayList($type) { $object = $type."PlayListDelegation"; $this->_object = new $object(); } function addSong($location,$title) { $this->_songs[] = array("location"=>$location,"title"=>$title); } function getPlayList() { return $this->_object->getPlayList($this->_songs); } } class mp3PlayListDelegation { function getPlayList($songs) { $aResult = array(); foreach($songs as $key=>$item) { $path = pathinfo($item['location']); if(strtolower($item['extension']) == "mp3") { $aResult[] = $item; } } return $aResult; } } class rmvbPlayListDelegation { function getPlayList($songs) { $aResult = array(); foreach($songs as $key=>$item) { $path = pathinfo($item['location']); if(strtolower($item['extension']) == "rmvb") { $aResult[] = $item; } } return $aResult; } } $oMP3PlayList = new PlayList("mp3"); $oMP3PlayList->getPlayList(); $oRMVBPlayList = new PlayList("rmvb"); $oRMVBPlayList->getPlayList(); ?>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
php創(chuàng)建和刪除目錄函數(shù)介紹和遞歸刪除目錄函數(shù)分享
這篇文章主要介紹了php創(chuàng)建和刪除目錄函數(shù)介紹和遞歸刪除目錄函數(shù)分享,本文重點是對遞歸刪除目錄的自定義函數(shù)分享,需要的朋友可以參考下2014-11-11淺析application/x-www-form-urlencoded和multipart/form-data的區(qū)別
我們知道在通過POST方式向服務(wù)器發(fā)送AJAX請求時最好要通過設(shè)置請求頭來指定為application/x-www-form-urlencoded編碼類型。知道通過表單上傳文件時必須指定編碼類型為"multipart/form-data"。那么為什么要這么設(shè)置呢2014-06-06php array_map使用自定義的函數(shù)處理數(shù)組中的每個值
這篇文章主要介紹了php array_map使用自定義的函數(shù)處理數(shù)組中的每個值的相關(guān)資料,需要的朋友可以參考下2016-10-10晉城吧對DiscuzX進(jìn)行的前端優(yōu)化要點
晉城吧的服務(wù)器在美國,延遲相對國內(nèi)略微要高一些,所以優(yōu)化就顯得非常重要。2010-09-09yii框架源碼分析之創(chuàng)建controller代碼
我們可以看到有時會使用protected目錄下的controller,有時會使用module中controller,具體是如何處理的呢,請看如下的分析2011-06-06php禁用cookie后session設(shè)置方法分析
這篇文章主要介紹了php禁用cookie后session設(shè)置方法,分析了php相關(guān)配置文件的功能與設(shè)置方法,具有一定參考借鑒價值,需要的朋友可以參考下2016-10-10