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 相关文章推荐
一个简单实现多条件查询的例子
Oct 09 PHP
开发大型 PHP 项目的方法
Jan 02 PHP
PHP define函数的使用说明
Aug 27 PHP
PHP5函数小全(分享)
Jun 06 PHP
php对csv文件的读取,写入,输出下载操作详解
Aug 10 PHP
PHP实现通用alert函数的方法
Mar 11 PHP
PHP使用CURL实现多线程抓取网页
Apr 30 PHP
php实现登陆模块功能示例
Oct 20 PHP
php获得刚插入数据的id 的几种方法总结
May 31 PHP
PHP的介绍以及优势详细分析
Sep 05 PHP
laravel框架使用阿里云短信发送消息操作示例
Feb 15 PHP
php7 图形用户界面GUI 开发示例
Feb 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利用str_replace防注入的方法
2013/11/10 PHP
浅谈PHP封装CURL
2019/03/06 PHP
教你如何解密js/vbs/vbscript加密的编码异处理小结
2008/06/25 Javascript
JavaScript Sort 表格排序
2009/10/31 Javascript
Extjs中通过Tree加载右侧TabPanel具体实现
2013/05/05 Javascript
NODE.JS加密模块CRYPTO常用方法介绍
2014/06/05 Javascript
使用Javascript简单实现图片无缝滚动
2014/12/05 Javascript
jQuery中addClass()方法用法实例
2015/01/05 Javascript
Jsonp post 跨域方案
2015/07/06 Javascript
jQuery实现选项卡切换效果简单演示
2015/12/09 Javascript
this,this,再次讨论javascript中的this,超全面(经典)
2016/01/05 Javascript
JavaScript检查子字符串是否在字符串中的方法
2016/02/03 Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
2016/12/08 Javascript
Angular4 反向代理Details实践
2018/05/30 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
2019/02/22 Javascript
layui+jquery支持IE8的表格分页方法
2019/09/28 jQuery
nodejs实现百度舆情接口应用示例
2020/02/07 NodeJs
vue中element 的upload组件发送请求给后端操作
2020/09/07 Javascript
详解JavaScript编程中的window与window.screen对象
2015/10/26 Python
Python数据类型详解(二)列表
2016/05/08 Python
详解Python if-elif-else知识点
2018/06/11 Python
详解如何用django实现redirect的几种方法总结
2018/11/22 Python
Python笔记之代理模式
2019/11/20 Python
Python基础之函数原理与应用实例详解
2020/01/03 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
2020/01/19 Python
基于Python实现简单学生管理系统
2020/07/24 Python
在 Windows 下搭建高效的 django 开发环境的详细教程
2020/07/27 Python
python 用opencv实现霍夫线变换
2020/11/27 Python
CSS实现的一闪而过的图片闪光效果
2014/04/23 HTML / CSS
英国豪华装饰照明品牌的在线零售商:Inspyer Lighting
2019/12/10 全球购物
农村婚礼证婚词
2014/01/08 职场文书
买卖车协议书
2014/04/21 职场文书
小学课外阅读总结
2014/07/09 职场文书
中秋节活动总结
2014/08/29 职场文书
2014年个人业务工作总结
2014/11/17 职场文书
导师鉴定意见
2015/06/05 职场文书