«
PHP4 中实现动态代理

时间:2008-5-31    作者:Deri    分类: 分享


    <p>  <a href="http://file.ddvip.com/2006_04/1144469838_ddvip_3417.zip">本文示例源代码或素材下载</a></p>

   <p>  一、 摘要</p><p>  本文简单阐述了 Proxy 模式及具体说明了如何在 PHP4 中实现动态代理,本文只是给出了一个实现的方法的原型。由于水平有限,有任何意见和建议请反馈给 Binzy [ Binzy at JustDN dot Com ]。</p><p>  二、 概述</p><p>  在我们开始实现 Dynamic Proxy 之前,也许我们应该先了解一下什么是 Proxy 和它有什么用。下面是一篇来自博客堂加菲猫的不错的形象讲述 Proxy 的文章: “武当学艺与缓存代理”。Proxy 模式是“GoF”介绍的23个设计模式之一,Proxy 的目的是“ Provide a surrogate or placeholder for another object to control access to it(为其他对象提供一种代理以控制对这个对象的访问)”。一般常见的代理模式有:远程代理(Remote Proxy),虚代理(Virtual Proxy),保护代理(Protection Proxy),智能代理(Smart Proxy)。</p><p>  但是使用代理有一个坏处就是你得手动创建所需要代理类的副本(即代理类)。这意味着如果你为 Image 类创建一个 Virtual Proxy,那么你不得不手动创建一个与 Image 类有相同 Method 的 ImageProxy 类。Ok,如果你和我一样懒,你一定会想到动态来产生Proxy。是的,接下来你就会发现,其实在PHP4中你很容易实现它。</p><p>  三、 实现</p><p>  由于 PHP4 是解释型语言,弱类型,且无接口。所以在实现的时候既有方便之处又有不妥之处。此处不拘泥于实现方法,本文也只是实现方法之一。</p><p>  本文实现的策略其实非常简单。核心即 ProxyFactory 类及 Clazz 类,ProxyFactory 负责实例化 Clazz,并赋值。而由 Clazz 类负责创建并返回 Proxy。创建 Proxy 是以写入临时文件方式进行的。</p><p>  具体请查看 ProxyFactory.php 和 Clazz.php 二个文件中的代码。此处不再赘述。</p>
<p> </p>

   <p>  另外在 ProxyInvocationHandler.php 中我们定义了一个 ProxyInvocationHandler 类。</p><p>  四、 示例</p><p>  我们现在有一个 ReadFileClass 类,该类继承自 IReadFileClass,由于 PHP4 没有接口,所以此处接口算是模拟的,事实上在PHP4中不使用实现接口也是可行的J。二个类的具体内容请见清单一和清单二。</p><p>  清单一</p><p>  <code>class IReadFileClass<br />{<br />  function ReadMyFile() {}<br />}</code></p><p>  清单二</p><p>  <code>class ReadFileClass extends IReadFileClass<br />{<br />  function ReadMyFile()<br />  {<br />    $fp = fopen('test.txt', "r");<br />    $data = fread($fp, filesize('test.txt'));<br />    fclose($fp);<br />    return $data;<br />  }<br />}</code></p><p>  OK,我们现在要加入验证用户的功能,即为 ReadFileClass 中的方法加入保护控制。如果采用手动创建代理,那么你可以继承 ReadFileClass 或者实现 IReadFileClass,并加入保护代码(其实在 PHP4 中甚为自由,因为除了基本类型外都是 object -_-)。不过我们现在试试用刚才实现的动态代理来创建 Proxy。</p><p>  请看清单三的 ReadFileClassProxy 的代码,注意该类继承自 ProxyInvocationHandler 类。</p><p>  清单三 </p><p>  <code>require_once('ProxyFactory.php');<br />require_once('ProxyInvocationHandler.php');<br />require_once('Auth.php');<br />class ReadFileClassProxy extends ProxyInvocationHandler<br />{<br />  var $object;<br />  function ReadFileClassProxy(&$obj)<br />  {<br />    $this->object = &$obj;<br />  }<br />  //<br />  function NewInstance(&$obj)<br />  {<br />    $proxyFactory = ProxyFactoryInstance();<br />    return $proxyFactory->create(new ReadFileClassProxy(&$obj),<br />    get_parent_class(&$obj));<br />  }<br />  // $proxy is not used here,but it is useful.<br />  function Invoke(&$proxy, $method, $parameters)<br />  {<br />    $uname = 'Binzy';<br />    //$uname = 'Jasmin';<br />    if (Auth::CheckAuth($uname))<br />    {<br />      Return parent::Invoke(&$proxy, $method, $parameters);<br />    }<br />    else<br />    {<br />      //<br />      return 'No Permission!';<br />    }<br />  }<br />}</code></p>
 <p> </p>

   <p>  Auth 类是一个进行权限验证的类,此处我们只是简单的查看传入的 UserName,如果是 Binzy,那么自然是可以看秘密的 J,如果是 Jasmin,那么 HoHo,没得看,给 Binzy 点空间嘛&#160;<img src="/content/uploadfile/200805/2008053117290816.gif" onclick="get_larger(this)" />&#160;详见清单四。</p><p>  清单四 </p><p>  <code>class Auth<br />{<br />  function Auth()<br />  {<br />  }<br />  // bool<br />  //<br />  function CheckAuth($username)<br />  {<br />    if ($username == 'Binzy')<br />    {<br />      return true;<br />    }<br />    return false;<br />  }<br />}</code></p><p>  Ok,下面我们来使用我们创建的代理。请见清单五.</p><p>  清单五 </p><p>  require_once('ReadFileClass.php');</p><p>  require_once('ReadFileClassProxy.php');</p><p>  $proxy = ReadFileClassProxy::NewInstance(new ReadFileClass());</p><p>  print $proxy->ReadMyFile();</p><p>  结果如下:</p><p>  如果是Binzy,那么自然可以知道那个秘密。</p><img src="/content/uploadfile/200805/2008053117290900.gif" onclick="get_larger(this)" /></p><p>  如果是Jasmin,这个秘密当然不能让她知道.</p><img src="/content/uploadfile/200805/2008053117290939.gif" onclick="get_larger(this)" /><p>  五、 总结<p>  代理是一个非常有用的模式。PHP4 虽然并不是真正的 Object-Oriented,但仍然可以实现你想实现的设计。写本文的目的有很大部分是希望国内 PHP 开发者不要再拘泥于现在的开发现状,开发出更好的 PHP 软件。而不是一堆 Script 的堆积。</p></p><p>  六、 感谢</p><p>  感谢好友 Freeman 为我做测试。</p><p>  感谢 mmkk 的 Code Formatter HTC。</p><p>  七、 参考</p><p>  1。GoF</p><p>  2。GoF中译本</p><p>  3。PHP参考手册 http://www.php.net/manual/en/</p></p>