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 mysql数据库操作类
Jun 04 PHP
使用PHP Socket 编程模拟Http post和get请求
Nov 25 PHP
PHP实现股票趋势图和柱形图
Feb 07 PHP
windows下apache搭建php开发环境
Aug 27 PHP
PHP定时执行任务的3种方法详解
Dec 21 PHP
CI框架扩展系统核心类的方法分析
May 23 PHP
微信红包随机生成算法php版
Jul 21 PHP
PHP处理Ajax请求与Ajax跨域问题
Feb 13 PHP
php curl上传、下载、https登陆实现代码
Jul 23 PHP
PHP绕过open_basedir限制操作文件的方法
Jun 10 PHP
Laravel 修改验证异常的响应格式实例代码详解
May 25 PHP
laravel添加角色和模糊搜索功能的实现代码
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
php IP转换整形(ip2long)的详解
2013/06/06 PHP
php中读写文件与读写数据库的效率比较分享
2013/10/19 PHP
PHP5.0 TIDY_PARSE_FILE缓冲区溢出漏洞的解决方案
2018/10/14 PHP
PHP递归算法的简单实例
2019/02/28 PHP
用JS实现3D球状标签云示例代码
2013/12/01 Javascript
javascript内置对象操作详解
2015/02/04 Javascript
JS实现进入页面时渐变背景色的方法
2015/02/25 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
2015/08/05 Javascript
深入理解bootstrap框架之入门准备
2016/10/09 Javascript
vue router2.0二级路由的简单使用
2017/07/05 Javascript
jQuery 实时保存页面动态添加的数据的示例
2017/08/14 jQuery
详解vue在项目中使用百度地图
2019/03/26 Javascript
vue框架制作购物车小球动画效果实例代码
2019/09/26 Javascript
webpack3升级到webpack4遇到问题总结
2019/09/30 Javascript
python+opencv实现动态物体识别
2018/01/09 Python
Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法
2018/04/22 Python
Django 登陆验证码和中间件的实现
2018/08/17 Python
Python中GIL的使用详解
2018/10/03 Python
python tkinter基本属性详解
2019/09/16 Python
python函数声明和调用定义及原理详解
2019/12/02 Python
jupyter实现重新加载模块
2020/04/16 Python
css3利用transform变形结合事件完成扇形导航
2020/10/26 HTML / CSS
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
html5 Canvas绘制线条 closePath()实例代码
2012/05/10 HTML / CSS
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
中学老师的自我评价
2013/11/07 职场文书
春节联欢会策划方案
2014/05/16 职场文书
法人委托书的范本格式
2014/09/11 职场文书
教师党员个人剖析材料
2014/09/29 职场文书
2014统计局民主生活会对照检查材料思想汇报
2014/10/02 职场文书
学雷锋日活动总结
2015/02/06 职场文书
2015年度销售个人工作总结
2015/03/31 职场文书
2015年母亲节活动策划方案
2015/05/04 职场文书
走进科学观后感
2015/06/18 职场文书
党员反邪教心得体会
2016/01/15 职场文书
刚学完怎么用Python实现定时任务,转头就跑去撩妹!
2021/06/05 Python