php设计模式之委托模式


Posted in PHP onFebruary 13, 2016

委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。
动态委托的介绍:动态委托概念来自于Jakarta 字节码工程库 (Byte-Code Engineering Library, BCEL)。它能够分析存在的类,并且对于接口,抽象类,甚至运行时的具体类来说,它能够生成以字节编码委托类。
被委托的接口/类应该满足如下条件:动态委托最多只能委托一个类,但是能够代理多个接口。这个限制来自于Java的单继承模式。一个Java类最多只有一个父类。既然生成的委托类把被委托类作为它的父类,那么指定多个被委托类是不合理的。如果没有指定被委托类,那么缺省的父类就是Object。
下面是PHP 反射机制实现动态代理的代码:

<?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();

// 运行结果

// Generate an Apple
?>

可见,通过代理类FruitDelegator来代替Fruit类来实现他的方法。
同样的,如下的代码也是能够运行的:

<?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();

?>

设计了一个cd类,类中有mp3播放模式,和mp4播放模式
改进前,使用cd类的播放模式,需要在实例化的类中去判断选择什么方式的播放模式
改进后,播放模式当做一个参数传入playList函数中,就自动能找到对应需要播放的方法。

一、未改进前

<?php 
//使用委托模式之前,调用cd类,选择cd播放模式是复杂的选择过程 
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(); 
}

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

<?php
 
namespace Tools;
 
/*
委托模式
去除核心对象中的判决和复杂功能性
*/
 
//委托接口
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');//只要传递参数就能知道需要选择何种播放模式

再为大家分享一个实例:

<?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();
?>

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

PHP 相关文章推荐
让你的PHP同时支持GIF、png、JPEG
Oct 09 PHP
利用discuz自带通行证整合dedecms的方法以及文件下载
Mar 06 PHP
使用JSON实现数据的跨域传输的php代码
Dec 20 PHP
php 备份数据库代码(生成word,excel,json,xml,sql)
Jun 23 PHP
php的sso单点登录实现方法
Jan 08 PHP
php与Mysql的一些简单的操作
Feb 26 PHP
浅析PHP中Session可能会引起并发问题
Jul 23 PHP
php实现scws中文分词搜索的方法
Dec 25 PHP
PHP环境搭建(php+Apache+mysql)
Nov 14 PHP
解决PHP上传非标准格式的图片pjpeg失败的方法
Mar 12 PHP
PHP多进程编程之僵尸进程问题的理解
Oct 15 PHP
Yii 使用intervention/image拓展实现图像处理功能
Jun 22 PHP
PHP常用设计模式之委托设计模式
Feb 13 #PHP
php判断邮箱地址是否存在的方法
Feb 13 #PHP
php打包网站并在线压缩为zip
Feb 13 #PHP
php session 写入数据库
Feb 13 #PHP
php等比例缩放图片及剪切图片代码分享
Feb 13 #PHP
PHP信号量基本用法实例详解
Feb 12 #PHP
PHP消息队列用法实例分析
Feb 12 #PHP
You might like
第十一节--重载
2006/11/16 PHP
Zend Studio 无法启动的问题解决方法
2008/12/04 PHP
javascript css float属性的特殊写法
2008/11/13 Javascript
从jQuery.camelCase()学习string.replace() 函数学习
2011/09/13 Javascript
js实现网页自动刷新可制作节日倒计时效果
2014/05/27 Javascript
js识别不同浏览器基于userAgent做判断
2014/07/29 Javascript
JavaScript学习笔记之取数组中最大值和最小值
2016/03/23 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
jQuery Easyui DataGrid点击某个单元格即进入编辑状态焦点移开后保存数据
2016/08/15 Javascript
浅谈Vue的基本应用
2016/12/27 Javascript
BootStrap Fileinput初始化时的一些参数
2016/12/30 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
vue.js组件vue-waterfall-easy实现瀑布流效果
2017/08/22 Javascript
微信小程序 配置顶部导航条标题颜色的实现方法
2017/09/20 Javascript
解决VUEX兼容IE上的报错问题
2018/03/01 Javascript
解决vue 格式化银行卡(信用卡)每4位一个符号隔断的问题
2018/09/14 Javascript
ng-repeat指令在迭代对象时的去重方法
2018/10/02 Javascript
在Create React App中启用Sass和Less的方法示例
2019/01/16 Javascript
npm的lock机制解析
2019/06/20 Javascript
JavaScript canvas实现雪花随机动态飘落
2020/02/08 Javascript
解决vue中el-tab-pane切换的问题
2020/07/19 Javascript
用Javascript实现发送短信验证码间隔功能
2021/02/08 Javascript
[40:19]2018完美盛典CS.GO表演赛
2018/12/17 DOTA
python通过线程实现定时器timer的方法
2015/03/16 Python
浅谈python字符串方法的简单使用
2016/07/18 Python
Python换行与不换行的输出实例
2020/02/19 Python
python2.7使用scapy发送syn实例
2020/05/05 Python
基于python实现简单网页服务器代码实例
2020/09/14 Python
Python 如何实现数据库表结构同步
2020/09/29 Python
英国豪华针织品牌John Smedley的在线销售商:The Outlet by John Smedley
2018/04/08 全球购物
SheIn沙特阿拉伯:女装在线
2020/03/23 全球购物
销售主管的自我评价分享
2014/01/03 职场文书
学校师德承诺书
2014/05/23 职场文书
阅兵口号
2014/06/19 职场文书
个人工作决心书
2015/09/22 职场文书
小学语文教师研修感悟
2015/11/18 职场文书