当前位置:首页 > PHP教程 > php高级应用 > 列表

php设计模式之委托模式

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-09 15:00:43 浏览: 评论:0 

这篇文章主要为大家详细介绍了php设计模式之委托模式,以一个实例为大家介绍了php委托模式,感兴趣的朋友可以参考一下。

委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。

动态委托的介绍:动态委托概念来自于Jakarta 字节码工程库 (Byte-Code Engineering Library, BCEL)。它能够分析存在的类,并且对于接口,抽象类,甚至运行时的具体类来说,它能够生成以字节编码委托类。

被委托的接口/类应该满足如下条件:动态委托最多只能委托一个类,但是能够代理多个接口。这个限制来自于Java的单继承模式。一个Java类最多只有一个父类。既然生成的委托类把被委托类作为它的父类,那么指定多个被委托类是不合理的。如果没有指定被委托类,那么缺省的父类就是Object。

下面是PHP 反射机制实现动态代理的代码:

  1. <?php 
  2. class Fruit 
  3.  
  4.  
  5.   function callFruit() 
  6.  
  7.   { 
  8.     print "Generate an Apple"
  9.   } 
  10.  
  11.  
  12. class FruitDelegator 
  13.  private $targets
  14.   function __construct() 
  15.   { 
  16.     $this->target[] = new Fruit(); 
  17.   } 
  18.     
  19.   function __call($name$args
  20.  
  21.   { 
  22.     foreach ($this->target as $obj
  23.     { 
  24.       $r = new ReflectionClass($obj); 
  25.       if ($method = $r->getMethod($name)) 
  26.  
  27.       { 
  28.  
  29.         if ($method->isPublic() && !$method->isAbstract()) 
  30.         { 
  31.  
  32.           return $method->invoke($obj$args); 
  33.         } 
  34.  
  35.       } 
  36.  
  37.     } 
  38.   } 
  39.  
  40.  
  41. $obj = new FruitDelegator(); 
  42.  
  43. $obj->callFruit(); 
  44.  
  45. // 运行结果 
  46.  
  47. // Generate an Apple 
  48. ?> 

可见,通过代理类FruitDelegator来代替Fruit类来实现他的方法。

同样的,如下的代码也是能够运行的:

  1. <?php 
  2. class Color 
  3.  
  4.   function callColor() 
  5.   { 
  6.     print "Generate Red"
  7.   } 
  8.    
  9.  
  10. class ColorDelegator 
  11.  
  12.  
  13.   private $targets
  14.  
  15.      
  16.  
  17.   function addObject($obj
  18.  
  19.   { 
  20.  
  21.     $this->target[] = $obj
  22.  
  23.   } 
  24.  
  25.      
  26.  
  27.   function __call($name$args
  28.  
  29.   { 
  30.  
  31.     foreach ($this->target as $obj
  32.  
  33.     { 
  34.  
  35.       $r = new ReflectionClass($obj); 
  36.  
  37.       if ($method = $r->getMethod($name)) 
  38.  
  39.       { 
  40.  
  41.         if ($method->isPublic() && !$method->isAbstract()) 
  42.  
  43.         { 
  44.           return $method->invoke($obj$args); 
  45.         } 
  46.       } 
  47.     } 
  48.   } 
  49.  
  50. $obj = new ColorDelegator(); 
  51. $obj->addObject(new Color()); 
  52. $obj->callColor(); 
  53.  
  54. ?> 

设计了一个cd类,类中有mp3播放模式,和mp4播放模式

改进前,使用cd类的播放模式,需要在实例化的类中去判断选择什么方式的播放模式

改进后,播放模式当做一个参数传入playList函数中,就自动能找到对应需要播放的方法。

一、未改进前

  1. <?php  
  2. //使用委托模式之前,调用cd类,选择cd播放模式是复杂的选择过程  
  3. class cd {  
  4.  protected $cdInfo = array();  
  5.     
  6.  public function addSong($song) {  
  7.   $this->cdInfo[$song] = $song;  
  8.  }  
  9.     
  10.  public function playMp3($song) {  
  11.   return $this->cdInfo[$song] . '.mp3';  
  12.  }  
  13.     
  14.  public function playMp4($song) {  
  15.   return $this->cdInfo[$song] . '.mp4';  
  16.  }  
  17. }  
  18. $oldCd = new cd;  
  19. $oldCd->addSong("1");  
  20. $oldCd->addSong("2");  
  21. $oldCd->addSong("3");  
  22. $type = 'mp3';  
  23. if ($type == 'mp3') {  
  24.  $oldCd->playMp3();  
  25. else {  
  26.  $oldCd->playMp4();  

二、通过委托模式,改进后的cd类

  1. <?php 
  2.    
  3. namespace Tools; 
  4.    
  5. /* 
  6. 委托模式 
  7. 去除核心对象中的判决和复杂功能性 
  8. */ 
  9.    
  10. //委托接口 
  11. interface Delegate{ 
  12.  public function playList($list,$song); 
  13.    
  14. //mp3处理类 
  15. class mp3 implements Delegate{ 
  16.  public function playList($list,$song){ 
  17.   return $list[$song].'.mp3'
  18.  } 
  19.    
  20. //mp4处理类 
  21. class mp4 implements Delegate{ 
  22.  public function playList($list$song
  23.  { 
  24.   return $list[$song].'.mp4'
  25.  } 
  26.    
  27. class cdDelegate{ 
  28.  protected $cdInfo = array(); 
  29.    
  30.  public function addSong($song){ 
  31.   $this->cdInfo[$song] = $song
  32.  } 
  33.    
  34.  public function play($type,$song){ 
  35.   $name = '\Tools\\'.$type
  36.   $obj = new $name
  37.   return $obj->playList($this->cdInfo,$song); 
  38.  } 
  39.    
  40. $newCd = new cdDelegate(); 
  41. $newCd->addSong("1"); 
  42. $newCd->addSong("2"); 
  43. $newCd->addSong("3"); 
  44. echo $newCd->play('mp3','1');//只要传递参数就能知道需要选择何种播放模式 

再为大家分享一个实例:

  1. <?php 
  2. /** 
  3.  * 委托模式 示例 
  4.  * 
  5.  * @create_date: 2010-01-04 
  6.  */ 
  7. class PlayList 
  8.  var $_songs = array(); 
  9.  var $_object = null; 
  10.    
  11.  function PlayList($type
  12.  { 
  13.   $object = $type."PlayListDelegation"
  14.   $this->_object = new $object(); 
  15.  } 
  16.    
  17.  function addSong($location,$title
  18.  { 
  19.   $this->_songs[] = array("location"=>$location,"title"=>$title); 
  20.  } 
  21.    
  22.  function getPlayList() 
  23.  { 
  24.   return $this->_object->getPlayList($this->_songs); 
  25.  } 
  26.    
  27. class mp3PlayListDelegation 
  28.  function getPlayList($songs
  29.  { 
  30.   $aResult = array(); 
  31.   foreach($songs as $key=>$item
  32.   { 
  33.    $path = pathinfo($item['location']); 
  34.    if(strtolower($item['extension']) == "mp3"
  35.    { 
  36.     $aResult[] = $item
  37.    } 
  38.   } 
  39.   return $aResult
  40.  } 
  41.    
  42. class rmvbPlayListDelegation 
  43.  function getPlayList($songs
  44.  { 
  45.   $aResult = array(); 
  46.   foreach($songs as $key=>$item
  47.   { 
  48.    $path = pathinfo($item['location']); 
  49.    if(strtolower($item['extension']) == "rmvb"
  50.    { 
  51.     $aResult[] = $item
  52.    } 
  53.   } 
  54.   return $aResult
  55.  } 
  56.    
  57. $oMP3PlayList = new PlayList("mp3"); 
  58. $oMP3PlayList->getPlayList(); 
  59. $oRMVBPlayList = new PlayList("rmvb"); 
  60. $oRMVBPlayList->getPlayList(); 
  61. ?> 

以上就是本文的全部内容,希望对大家的学习有所帮助。

Tags: php设计模式 php委托模式

分享到: