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 相关文章推荐
改进的IP计数器
Oct 09 PHP
怎样在UNIX系统下安装MySQL
Oct 09 PHP
PHP导出MySQL数据到Excel文件(fputcsv)
Jul 03 PHP
PHP MySQL应用中使用XOR运算加密算法分享
Aug 28 PHP
destoon数据库表说明汇总
Jul 15 PHP
ThinkPHP打开验证码页面显示乱码的解决方法
Dec 18 PHP
php简单获取目录列表的方法
Mar 24 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
Jan 07 PHP
使用JavaScript创建新样式表和新样式规则
Jun 14 PHP
PHP遍历目录文件的常用方法小结
Feb 03 PHP
Laravel 添加多语言提示信息的方法
Sep 29 PHP
如何用PHP实现分布算法之一致性哈希算法
May 26 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
php mb_substr()函数截取中文字符串应用示例
2014/07/29 PHP
php中getservbyport与getservbyname函数用法实例
2014/11/18 PHP
php实现搜索一维数组元素并删除二维数组对应元素的方法
2015/07/06 PHP
基于ThinkPHP实现批量删除
2015/12/18 PHP
jquery中子元素和后代元素的区别示例介绍
2014/04/02 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
Vuejs第十三篇之组件——杂项
2016/09/09 Javascript
jquery日历插件e-calendar升级版
2016/11/10 Javascript
js封装tab标签页实例分享
2016/12/19 Javascript
Javascript实现登录记住用户名和密码功能
2017/03/22 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
运用js实现图层拖拽的功能
2019/05/24 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
JavaScript的垃圾回收机制与内存管理
2020/08/06 Javascript
[01:20]DOTA2更新全新英雄 天涯墨客现已加入游戏
2018/08/25 DOTA
python中的内置函数getattr()介绍及示例
2014/07/20 Python
Python中optionParser模块的使用方法实例教程
2014/08/29 Python
Python编程中对super函数的正确理解和用法解析
2016/07/02 Python
Python3.4 splinter(模拟填写表单)使用方法
2018/10/13 Python
pycharm 取消默认的右击运行unittest的方法
2018/11/29 Python
Windows下Anaconda和PyCharm的安装与使用详解
2020/04/23 Python
python 两种方法删除空文件夹
2020/09/29 Python
纯css3显示隐藏一个div特效的具体实现
2014/02/10 HTML / CSS
俄罗斯宠物用品网上商店:ZooMag
2019/12/12 全球购物
会计自我鉴定范文
2013/10/06 职场文书
高三自我鉴定
2013/10/23 职场文书
公司活动邀请函
2014/01/24 职场文书
房地产项目策划书
2014/02/05 职场文书
项目合作协议书范本
2014/04/16 职场文书
高中生第一学年自我鉴定2015
2014/09/28 职场文书
2014年妇产科工作总结
2014/12/08 职场文书
工程进度款催款函
2015/06/24 职场文书
小学语文国培研修日志
2015/11/13 职场文书
python tkinter模块的简单使用
2021/04/07 Python
AI:如何训练机器学习的模型
2021/04/16 Python
浅谈JS的原型和原型链
2021/06/04 Javascript