PHP設計模式漫談之代理模式
原創【51CTO獨家特稿】設計模式( Design Pattern)是從建筑設計領域引入到計算機科學的。設計模式是對軟件設計中普遍存在(且反復出現)的各種問題,所提出的解決方案。設計模式并不直接用來完成程序碼的編寫,而是描述在各種不同情況下,要怎么解決問題的一種方案。
更多關于PHP設計模式方面的入門與應用可以參考51CTO之前的報道《使用設計模式改善程序結構》以及《架構、框架、設計模式之間的關系簡述》。
我們經常看到關于Java和.NET平臺上設計模式的論述和講解,其實,在PHP 5對面向對象的支持更加完善之后,設計模式的應用也可引入到PHP中并發揮重要作用。51CTO.com將從本周起以每周一期的形式連載《PHP設計模式漫談》的系列文章,以理論與代碼實例相結合的方式講解PHP中的設計模式。希望對從事PHP研發的讀者有所幫助。
今天我們要談的是PHP設計模式中的代理模式(Proxy),它是對簡單處理程序(或指針)的增強,用于引用一個對象:這個指針被代理(Proxy)對象取代,代理對象位于客戶端(Client)和真實執行程序之間,指針有一個可被多個目標利用的鉤子。
從技術上講,這種模式在客戶端和真實主體(RealSubject)之間插入一個代理對象,維護subject接口和用不同的方式委派它的方法。代理可以透明地做任何事情:懶散創建RealSubject或載入數據,與其它機器交換消息,寫時復制策略等。這與HTTP代理有點類似,其客戶端(如瀏覽器)和應用程序依賴于與HTTP服務器的聯系,代理在管理連接時可以完成其它任務,如訪問控制和緩存大型下載文件。
代理模式的對象圖與裝飾模式對象圖在結構上類似,但表達的目的各有不同,裝飾者給對象動態增加行為,而代理則控制來自客戶端的訪問。此外,代理只在需要時才創建RealSubject。
參與者:
◆客戶端(Client):取決于主體(Subject)實現;
◆主體(Subject):RealSubject的抽象;
◆真實主體(RealSubject):完成代價高昂的工作或包含大量的數據;
◆代理(Proxy):為Client提供一個與Subject一致的引用,僅在需要時才創建RealSubject實例或與RealSubject實例通信。
下面是兩個被廣泛使用的代理模式例子:
1、對象-關系映射(Orms)在運行中創建代理作為實體類的子類,以實現懶散加載(虛擬代理),這個代理會覆蓋所有實體方法,在前面追加一個載入程序,在方法被真正調用前不會包含任何數據,Orms代理支持對象間的雙向關系,不用加載整個數據庫,因為它們被置于當前加載對象圖的邊界。
2、Java RMI使用遠程代理對象(遠程代理),當它們的方法被調用時,代理序列化參數,執行網絡上的請求,委托調用另一個節點上的真實對象,這種技術允許透明地調用遠程對象,不用擔心它們是否在同一臺機器上,但這種透明度很容易會使執行速度變慢。
下面的代碼示例實現了一個ImageProxy,推遲了圖像數據的加載。
- /**
- * Subject interface.
- * Client depends only on this abstraction.
- */
- interface Image
- {
- public function getWidth();
- public function getHeight();
- public function getPath();
- /**
- * @return string the image's byte stream
- */
- public function dump();
- }
- /**
- * Abstract class to avoid repetition of boilerplate code in the Proxy
- * and in the Subject. Only the methods which can be provided without
- * instancing the RealSubject are present here.
- */
- abstract class AbstractImage implements Image
- {
- protected $_width;
- protected $_height;
- protected $_path;
- protected $_data;
- public function getWidth()
- {
- return $this->_width;
- }
- public function getHeight()
- {
- return $this->_height;
- }
- public function getPath()
- {
- return $this->_path;
- }
- }
- /**
- * The RealSubject. Always loads the image, even if no dump of the data
- * is required.
- */
- class RawImage extends AbstractImage
- {
- public function __construct($path)
- {
- $this->_path = $path;
- list ($this->_width, $this->_height) = getimagesize($path);
- $this->_data = file_get_contents($path);
- }
- public function dump()
- {
- return $this->_data;
- }
- }
- /**
- * Proxy. Defers loading the image data until it becomes really mandatory.
- * This class does its best to postpone the very expensive operations
- * such as the actual loading of the BLOB.
- */
- class ImageProxy extends AbstractImage
- {
- public function __construct($path)
- {
- $this->_path = $path;
- list ($this->_width, $this->_height) = getimagesize($path);
- }
- /**
- * Creates a RawImage and exploits its functionalities.
- */
- protected function _lazyLoad()
- {
- if ($this->_realImage === null) {
- $this->_realImage = new RawImage($this->_path);
- }
- }
- public function dump()
- {
- $this->_lazyLoad();
- return $this->_realImage->dump();
- }
- }
- /**
- * Client class that does not use the data dump of the image.
- * Passing blindly a Proxy to this class and to other Clients makes sense
- * as the data would be loaded anyway when Image::dump() is called.
- */
- class Client
- {
- public function tag(Image $img)
- {
- return '
$img->getPath() . '" alt="" width="'
- . $img->getWidth() . '" height="'
- . $img->getHeight() . '" />';
- }
- }
- $path = '/home/giorgio/shared/Immagini/kiki.png';
- $client = new Client();
- $image = new RawImage($path); // loading of the BLOB takes place
- echo $client->tag($image), "\n";
- $proxy = new ImageProxy($path);
- echo $client->tag($proxy), "\n"; // loading does not take place even here
以上代碼實現了PHP的代理模式。簡單來講,代理模式就是為其他對象提供一個代理以控制對這個對象的訪問。
關于設計模式的其他方面
我們知道了什么是設計模式以及PHP設計模式中的代理模式。這里還有一些關于設計模式的基本概念應該被熟知。
◆算法不能算是一種設計模式,因為算法主要是用來解決計算上的問題,而非設計上的問題。
◆面向對象設計模式通常以類別或物件來描述其中的關系和相互作用,但不涉及用來完成應用程序的特定類別或物件。
◆設計模式主要是使不穩定的依賴于相對穩定、具體依賴于相對抽象,避免會引起麻煩的緊耦合,以增強軟件設計面對并適應變化的能力。
◆并非所有的軟件模式都是設計模式,設計模式特指軟件設計層次上的問題。還有其它非設計模式的模式,如架構模式。
我們會在下周繼續為您連載《PHP設計模式漫談》,敬請期待。
【編輯推薦】
原文:Practical Php Patterns: Proxy
鏈接:http://giorgiosironi.blogspot.com/2010/02/practical-php-patterns-proxy.html