php设计模式之委托模式
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。
动态委托的介绍:动态委托概念来自于Jakarta字节码工程库(Byte-CodeEngineeringLibrary,BCEL)。它能够分析存在的类,并且对于接口,抽象类,甚至运行时的具体类来说,它能够生成以字节编码委托类。
被委托的接口/类应该满足如下条件:动态委托最多只能委托一个类,但是能够代理多个接口。这个限制来自于Java的单继承模式。一个Java类最多只有一个父类。既然生成的委托类把被委托类作为它的父类,那么指定多个被委托类是不合理的。如果没有指定被委托类,那么缺省的父类就是Object。
下面是PHP反射机制实现动态代理的代码:
<?php classFruit { functioncallFruit() { print"GenerateanApple"; } } classFruitDelegator { private$targets; function__construct() { $this->target[]=newFruit(); } function__call($name,$args) { foreach($this->targetas$obj) { $r=newReflectionClass($obj); if($method=$r->getMethod($name)) { if($method->isPublic()&&!$method->isAbstract()) { return$method->invoke($obj,$args); } } } } } $obj=newFruitDelegator(); $obj->callFruit(); //运行结果 //GenerateanApple ?>
可见,通过代理类FruitDelegator来代替Fruit类来实现他的方法。
同样的,如下的代码也是能够运行的:
<?php classColor { functioncallColor() { print"GenerateRed"; } } classColorDelegator { private$targets; functionaddObject($obj) { $this->target[]=$obj; } function__call($name,$args) { foreach($this->targetas$obj) { $r=newReflectionClass($obj); if($method=$r->getMethod($name)) { if($method->isPublic()&&!$method->isAbstract()) { return$method->invoke($obj,$args); } } } } } $obj=newColorDelegator(); $obj->addObject(newColor()); $obj->callColor(); ?>
设计了一个cd类,类中有mp3播放模式,和mp4播放模式
改进前,使用cd类的播放模式,需要在实例化的类中去判断选择什么方式的播放模式
改进后,播放模式当做一个参数传入playList函数中,就自动能找到对应需要播放的方法。
一、未改进前
<?php //使用委托模式之前,调用cd类,选择cd播放模式是复杂的选择过程 classcd{ protected$cdInfo=array(); publicfunctionaddSong($song){ $this->cdInfo[$song]=$song; } publicfunctionplayMp3($song){ return$this->cdInfo[$song].'.mp3'; } publicfunctionplayMp4($song){ return$this->cdInfo[$song].'.mp4'; } } $oldCd=newcd; $oldCd->addSong("1"); $oldCd->addSong("2"); $oldCd->addSong("3"); $type='mp3'; if($type=='mp3'){ $oldCd->playMp3(); }else{ $oldCd->playMp4(); }
二、通过委托模式,改进后的cd类
<?php namespaceTools; /* 委托模式 去除核心对象中的判决和复杂功能性 */ //委托接口 interfaceDelegate{ publicfunctionplayList($list,$song); } //mp3处理类 classmp3implementsDelegate{ publicfunctionplayList($list,$song){ return$list[$song].'.mp3'; } } //mp4处理类 classmp4implementsDelegate{ publicfunctionplayList($list,$song) { return$list[$song].'.mp4'; } } classcdDelegate{ protected$cdInfo=array(); publicfunctionaddSong($song){ $this->cdInfo[$song]=$song; } publicfunctionplay($type,$song){ $name='\Tools\\'.$type; $obj=new$name; return$obj->playList($this->cdInfo,$song); } } $newCd=newcdDelegate(); $newCd->addSong("1"); $newCd->addSong("2"); $newCd->addSong("3"); echo$newCd->play('mp3','1');//只要传递参数就能知道需要选择何种播放模式
再为大家分享一个实例:
<?php /** *委托模式示例 * *@create_date:2010-01-04 */ classPlayList { var$_songs=array(); var$_object=null; functionPlayList($type) { $object=$type."PlayListDelegation"; $this->_object=new$object(); } functionaddSong($location,$title) { $this->_songs[]=array("location"=>$location,"title"=>$title); } functiongetPlayList() { return$this->_object->getPlayList($this->_songs); } } classmp3PlayListDelegation { functiongetPlayList($songs) { $aResult=array(); foreach($songsas$key=>$item) { $path=pathinfo($item['location']); if(strtolower($item['extension'])=="mp3") { $aResult[]=$item; } } return$aResult; } } classrmvbPlayListDelegation { functiongetPlayList($songs) { $aResult=array(); foreach($songsas$key=>$item) { $path=pathinfo($item['location']); if(strtolower($item['extension'])=="rmvb") { $aResult[]=$item; } } return$aResult; } } $oMP3PlayList=newPlayList("mp3"); $oMP3PlayList->getPlayList(); $oRMVBPlayList=newPlayList("rmvb"); $oRMVBPlayList->getPlayList(); ?>
以上就是本文的全部内容,希望对大家的学习有所帮助。