PHP4中實現動態代理

來源:互聯網
上載者:User
關鍵字 PHP4中實現動態代理

作者:Binzy 來源:超越php

一、 摘要
本文簡單闡述了PRoxy模式及具體說明了如何在PHP4中實現動態代理, 本文只是給出了一個實現的方法的原型. 由於水平有限, 有任何意見和建議請反饋給Binzy [ Binzy at JustDN dot Com ].

二、 概述
在我們開始實現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).
但是使用代理有一個壞處就是你得手動建立所需要代理類的副本(即代理類). 這意味著如果你為Image類建立一個Virtual Proxy, 那麼你不得不手動建立一個與Image類有相同Method的ImageProxy類. Ok, 如果你和我一樣懶, 你一定會想到動態來產生Proxy. 是的, 接下來你就會發現, 其實在PHP4中你很容易實現它.

三、 實現
由於PHP4是解釋型語言, 弱類型, 且無介面. 所以在實現的時候既有方便之處又有不妥之處. 此處不拘泥於實現方法, 本文也只是實現方法之一.
本文實現的策略其實非常簡單. 核心即ProxyFactory類及Clazz類, ProxyFactory負責執行個體化Clazz, 並賦值. 而由Clazz類負責建立並返回Proxy. 建立Proxy是以寫入臨時檔案方式進行的.
具體請查看ProxyFactory.php和Clazz.php二個檔案中的代碼. 此處不再贅述.
另外在ProxyInvocationHandler.php中我們定義了一個ProxyInvocationHandler類.

四、 樣本
我們現在有一個ReadFileClass類, 該類繼承自IReadFileClass, 由於PHP4沒有介面, 所以此處介面算是類比的, 事實上在PHP4中不使用實現介面也是可行的J. 二個類的具體內容請見清單一和清單二.

清單一
class IReadFileClass
{
function ReadMyFile() {}
}

清單二
class ReadFileClass extends IReadFileClass
{
function ReadMyFile()
{

$fp = fopen('test.txt', "r");
$data = fread($fp, filesize('test.txt'));
fclose($fp);
return $data;
}
}

OK, 我們現在要加入驗證使用者的功能, 即為ReadFileClass中的方法加入保護控制. 如果採用手動建立代理, 那麼你可以繼承ReadFileClass或者實現IReadFileClass, 並加入保護代碼(其實在PHP4中甚為自由, 因為除了基本類型外都是object-_-). 不過我們現在試試用剛才實現的動態代理來建立Proxy.

請看清單三的ReadFileClassProxy的代碼, 注意該類繼承自ProxyInvocationHandler類.

清單三
require_once('ProxyFactory.php');
require_once('ProxyInvocationHandler.php');
require_once('Auth.php');

class ReadFileClassProxy extends ProxyInvocationHandler
{

var $object;

function ReadFileClassProxy(&$obj)
{
$this->object = &$obj;
}

//
function NewInstance(&$obj)
{
$proxyFactory = ProxyFactoryInstance();
return $proxyFactory->create(new ReadFileClassProxy(&$obj),
get_parent_class(&$obj));
}

// $proxy is not used here, but it is useful.
function Invoke(&$proxy, $method, $parameters)
{
$uname = 'Binzy';
//$uname = 'Jasmin';
if (Auth::CheckAuth($uname))
{
Return parent::Invoke(&$proxy, $method, $parameters);
}
else
{
//
return 'No Permission!';
}
}
}

Auth類是一個進行許可權驗證的類, 此處我們只是簡單的查看傳入的UserName, 如果是Binzy, 那麼自然是可以看秘密的J, 如果是Jasmin, 那麼HoHo, 沒得看, 給Binzy點空間嘛.:D 詳見清單四.

清單四
class Auth
{
function Auth()
{
}
// bool
//
function CheckAuth($username)
{
if ($username == 'Binzy')
{
return true;
}
return false;
}
}


Ok, 下面我們來使用我們建立的代理. 請見清單五.

清單五
require_once('ReadFileClass.php');
require_once('ReadFileClassProxy.php');

$proxy = ReadFileClassProxy::NewInstance(new ReadFileClass());
print $proxy->ReadMyFile();

結果如下:
如果是Binzy, 那麼自然可以知道那個秘密.

如果是Jasmin, 這個秘密當然不能讓她知道.

五、 總結
代理是一個非常有用的模式. PHP4雖然並不是真正的Object-Oriented, 但仍然可以實現你想實現的設計. 寫本文的目的有很大部分是希望國內PHP開發人員不要再拘泥於現在的開發現狀, 開發出更好的PHP軟體. 而不是一堆Script的堆積.

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.