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 相关文章推荐
基于HTTP长连接的&quot;服务器推&quot;技术的php 简易聊天室
Oct 31 PHP
PHP实现域名whois查询的代码(数据源万网、新网)
Feb 22 PHP
Cakephp 执行主要流程
Mar 24 PHP
与文件上传有关的php配置参数总结
Jun 14 PHP
PHP实现数组递归转义的方法
Aug 28 PHP
php校验表单检测字段是否为空的方法
Mar 20 PHP
php恢复数组的key为数字序列的方法
Apr 28 PHP
PHP基于单例模式实现的数据库操作基类
Jan 15 PHP
Yii2简单实现给表单添加验证码的方法
Jul 18 PHP
PHP实现的MD5结合RSA签名算法实例
Oct 07 PHP
PHP实现的ID混淆算法类与用法示例
Aug 10 PHP
PHP预定义接口――Iterator用法示例
Jun 05 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
ajax+php打造进度条代码[readyState各状态说明]
2010/04/12 PHP
PHP通过微信跳转的Code参数获取用户的openid(关键代码)
2016/07/06 PHP
JavaScript中null与undefined分析
2009/07/25 Javascript
JS判断是否为数字,是否为整数,是否为浮点数的代码
2010/04/24 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
JavaScript中的Web worker多线程API研究
2014/12/06 Javascript
jquery中object对象循环遍历的方法
2015/12/18 Javascript
js实现正则匹配中文标点符号的方法
2015/12/23 Javascript
jQuery中判断对象是否存在的方法汇总
2016/02/24 Javascript
微信小程序  modal弹框组件详解
2016/10/27 Javascript
BootStrap 标题设置跨行无效的解决方法
2017/10/25 Javascript
three.js中文文档学习之如何本地运行详解
2017/11/20 Javascript
Vuex入门到上手教程
2018/06/20 Javascript
jQuery实现为动态添加的元素绑定事件实例分析
2018/09/07 jQuery
js核心基础之构造函数constructor用法实例分析
2019/05/11 Javascript
JavaScript Reflect Metadata实现详解
2019/12/12 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
解决vue props传Array/Object类型值,子组件报错的情况
2020/11/07 Javascript
Python实现获取网站PR及百度权重
2015/01/21 Python
Python遍历指定文件及文件夹的方法
2015/05/09 Python
python向已存在的excel中新增表,不覆盖原数据的实例
2018/05/02 Python
Django实战之用户认证(初始配置)
2018/07/16 Python
python 3.8.3 安装配置图文教程
2020/05/21 Python
芭比波朗加拿大官方网站:Bobbi Brown Cosmetics CA
2020/11/05 全球购物
施华洛世奇新加坡官网:SWAROVSKI新加坡
2020/10/06 全球购物
建筑施工实习自我鉴定
2013/09/19 职场文书
师生聚会感言
2014/01/26 职场文书
市场部业务员岗位职责
2014/04/02 职场文书
建筑节能汇报材料
2014/08/22 职场文书
学习张林森心得体会
2014/09/10 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
工作简报格式范文
2015/07/21 职场文书
2016年暑假家长对孩子评语
2015/12/01 职场文书
党员公开承诺书(2016最新版)
2016/03/24 职场文书
一文搞懂Python Sklearn库使用
2021/08/23 Python
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技