概念
代理模式(Proxy Pattern) :一種物件結構型模式。給某一個物件一個代理,並由代理物件控制對原物件的參考。
UML
角色
抽象主題角色(Subject):定義了RealSubject和Proxy公用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy。
真正主題角色(RealSubject):定義了Proxy所代表的真實實體。
代理物件(Proxy):保存一個引用使得代理可以存取實體,並提供一個與RealSubject接口相同的接口,這樣代理可以用來代替實體(RealSubject)。
適用場景
根據代理模式的使用目的,常見的代理模式有以下幾種類型:
遠端(Remote)代理:為一個位於不同的地址空間的對象提供一個本地的代理對象,這個不同的位址空間可以是在同一台主機中,也可是在另一台主機中,遠端代理又叫做大使(Ambassador)。
虛擬(Virtual)代理:如果需要建立一個資源消耗較大的對象,先建立一個消耗相對較小的對象來表示,真實對像只在需要時才會被真正創建。
Copy-on-Write代理:它是虛擬代理的一種,把複製(克隆)操作延遲 到只有在客戶端真正需要時才執行。一般來說,物件的深克隆是一個 開銷較大的操作,Copy-on-Write代理可以讓這個操作延遲,只有物件被用到的時候才會被複製。
保護(Protect or Access)代理:控制對一個物件的訪問,可以給不同的使用者不同等級的使用權限。
緩衝(Cache)代理:為某一個目標操作的結果提供暫存的儲存空間,以便多個客戶端可以共用這些結果。
防火牆(Firewall)代理:保護目標不讓惡意使用者接近。
同步化(Synchronization)代理:使幾個使用者能夠同時使用一個物件而沒有衝突。
智能引用(Smart Reference)代理:當一個物件被引用時,提供一些額外的操作,如將此物件被呼叫的次數記錄下來等。
程式碼
程式碼如下:
<?php header("Content-type:text/html;Charset=utf-8"); /** * Interface Subject 抽象主题角色 * * 定义RealSubject和Proxy共同具备的东西 */ interface Subject { public function say(); public function run(); } /** * Class RealSubject 真正主题角色 */ class RealSubject implements Subject { // 姓名 private $_name; /** * RealSubject constructor. 构造方法 * * @param $name */ public function __construct($name) { $this->_name = $name; } /** * 说话 */ public function say() { echo $this->_name."在说话<br>"; } /** * 在跑步 */ public function run(){ echo $this->_name."在跑步<br>"; } } /** * Class Proxy 代理对象 */ class Proxy implements Subject { // 真实主题对象 private $_realSubject = null; /** * Proxy constructor. 构造方法,依赖注入方式储存真实对象 * * @param RealSubject|null $realSubject */ public function __construct(RealSubject $realSubject = null) { if (empty($realSubject)) { $this->_realSubject = new RealSubject(); } else { $this->_realSubject = $realSubject; } } /** * 调用说话方法 */ public function say() { $this->_realSubject->say(); } /** * 调用跑步方法 */ public function run() { $this->_realSubject->run(); } } /** * Class Client 本地测试 */ class Client { public static function test() { // 创建 $subject = new RealSubject("张三"); // 代理 $proxy = new Proxy($subject); // 张三在说话 $proxy->say(); // 张三在跑步 $proxy->run(); } } // 测试 Client::test();
運行結果:
張三在說話
張三在跑步
優點和缺點程度上降低了系統的耦合度。
遠端代理使得客戶端可以存取在遠端機器上的對象,遠端機器 可能具有更好的計算效能與處理速度,可以快速回應並處理客戶端請求。
虛擬代理透過使用一個小對象來代表一個大對象,可以減少系統資源的消耗,對系統進行最佳化並提高運行速度。
保護代理可以控制對真實物件的使用權限。
缺點:
由於在客戶端和真實主題之間增加了代理對象,因此 有些類型的代理模式可能會造成請求的處理速度變慢。
實作代理模式需要額外的工作,有些代理模式的實作非常複雜。