首頁  >  文章  >  後端開發  >  php實作代理模式的方法

php實作代理模式的方法

不言
不言原創
2018-07-05 10:45:304385瀏覽

這篇文章主要介紹了關於php實現代理模式的方法,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

代理模式(Proxy Pattern) :

  給予某一個物件一個代理,並由代理物件控制對原始物件的參考。代理模式的英文叫做Proxy或Surrogate,它是一種物件結構型模式

模式動機:
  在某些情況下,一個客戶不想或不能直接引用一個對象,此時可以透過一個稱為「代理」的第三者來實現間接引用。代理對象可以在客戶端和目標對象之間起到 中介的作用,並且可以透過代理對象去掉客戶不能看到 的內容和服務或添加客戶需要的額外服務。
  透過引入一個新的物件(如小圖片和遠端代理物件)來實現對真實物件的操作或將新的物件作為真實物件的一個替身,這種實作機制即為代理模式,透過引入代理對象來間接存取一個對象,這就是代理模式的模式動機。

代理模式包含以下角色:
  抽象主題角色(Subject):定義了RealSubject和Proxy公用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy。
  真正主題角色(RealSubject):定義了Proxy所代表的真實實體。
  代理物件(Proxy):保存一個引用使得代理可以存取實體,並提供一個與RealSubject接口相同的接口,這樣代理可以用來代替實體(RealSubject)。

UML圖:

程式碼實作:

<?php
header("Content-type:text/html;Charset=utf-8");//定义RealSubject和Proxy共同具备的东西
interface Subject{    
function say();    
function run();
}
class RealSubject implements Subject{    
private $name;    
function __construct($name){        
$this->name = $name;
    }    function say(){        
    echo $this->name."在吃饭<br>";
    }    function run(){        
    echo $this->name."在跑步<br>";
    }
}
class Proxy implements Subject{    
private $realSubject = null;    
function __construct(RealSubject $realSubject = null){        
if(empty($realSubject)){            
$this->realSubject = new RealSubject();
        }else{            
        $this->realSubject = $realSubject;
        }
    }    function say(){        
    $this->realSubject->say();
    }    function run(){        
    $this->realSubject->run();
    }
}//测试
$subject = new RealSubject("张三");
$proxy = new Proxy($subject);$proxy->say();
$proxy->run();
/*张三在吃饭
张三在跑步*/
?>

優點:
  代理模式能夠協調呼叫者和被呼叫者,在一定程度上降低了系統的耦合度。
  遠端代理使得客戶端可以存取在遠端機器上的對象,遠端機器 可能具有更好的計算效能與處理速度,可以快速回應並處理客戶端請求。
  虛擬代理程式透過使用一個小對象來代表一個大對象,可以減少系 統資源的消耗,對系統進行最佳化並提高運行速度。
  保護代理程式可以控制對真實物件的使用權限。

缺點:
  由於在客戶端和真實主題之間增加了代理對象,因此 有些類型的代理模式可能會造成請求的處理速度變慢。
  實作代理模式需要額外的工作,有些代理模式的實作 非常複雜。

適用場景:
  根據代理模式的使用目的,常見的代理模式有以下幾種類型:
  1、遠端(Remote)代理:為一個位於不同的位址空間的物件提供一個本地的代理對象,這個不同的地址空間可以是在同一台主機中,也可是在另一台主機中,遠端代理又叫做大使(Ambassador)。
  2、虛擬(Virtual)代理:如果需要建立一個資源消耗較大的對象,先建立一個消耗相對較小的對象來表示,真實對像只在需要時才會被真正創建。
  3、Copy-on-Write代理:它是虛擬代理的一種,把複製(克隆)操作延遲 到只有在客戶端真正需要時才執行。一般來說,物件的深克隆是一個 開銷較大的操作,Copy-on-Write代理可以讓這個操作延遲,只有物件被用到的時候才會被複製。
  4、保護(Protect or Access)代理:控制對一個物件的訪問,可以給不同的使用者提供不同層級的使用權限。
  5、緩衝(Cache)代理:為某一個目標操作的結果提供暫存的儲存空間,以便多個客戶端可以共用這些結果。
  6、防火牆(Firewall)代理:保護目標不讓惡意使用者接近。
  7、同步化(Synchronization)代理:使幾個使用者能夠同時使用一個物件而沒有衝突。
  8、智慧引用(Smart Reference)代理程式:當一個物件被引用時,提供一些額外的操作,如將此物件被呼叫的次數記錄下來等。

几种常用的代理模式:
  1、图片代理:一个很常见的代理模式的应用实例就是对大图浏览的控制。
  用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。当需要浏览大图片时,再将大图片在新网页中显示。如果用户在浏览大图时加载工作还没有完成,可以再启动一个线程来显示相应的提示信息。通过代理技术结合多线程编程将真实图片的加载放到后台来操作,不影响前台图片的浏览。
    2、远程代理:远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的远程业务对象是局域的而不是远程的,而远程代理对象承担了大部分的网络通信工作。
  3、虚拟代理:当一个对象的加载十分耗费资源的时候,虚拟代理的优势就非常明显地体现出来了。虚拟代理模式是一种内存节省技术,那些占用大量内存或处理复杂的对象将推迟到使用它的时候才创建。
  在应用程序启动的时候,可以用代理对象代替真实对象初始化,节省了内存的占用,并大大加速了系统的启动时间。
  4、动态代理:动态代理是一种较为高级的代理模式,它的典型应用就是Spring AOP。
  在传统的代理模式中,客户端通过Proxy调用RealSubject类的request()方法,同时还在代理类中封装了其他方法(如preRequest()和postRequest()),可以处理一些其他问题。
  如果按照这种方法使用代理模式,那么真实主题角色必须是事先已经存在的,并将其作为代理对象的内部成员属性。如果一个真实主题角色必须对应一个代理主题角色,这将导致系统中的类个数急剧增加,因此需要想办法减少系统中类的个数,此外,如何在事先不知道真实主题角色的情况下使用代理主题角色,这都是动态代理需要解决的问题。

另一个例子:

设计模式之代理模式(php实现)

github地址:https://github.com/ZQCard/design_pattern

/**
 * 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
 *  1、Windows 里面的快捷方式。
 * 2、猪八戒去找高翠兰结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,
 * 猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。
 * 3、买火车票不一定在火车站买,也可以去代售点。
 * 4、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。
 *优点:
 * 1、职责清晰。 2、高扩展性。 3、智能化。
 * 缺点:
 * 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
 * 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
 * 例子:从服务器读取一张图片的时候,第一次从硬盘读取,将资源对象代理,第二次读取的时候就使用代理对象去读取。 */

(1)Image.class.php(接口)

<?php

namespace Proxy;interface Image
{    public function display();
}

(2)RealImage.class.php

<?php

namespace Proxy;class RealImage implements Image
{    private $fileName;    public function __construct($fileName)
    {        $this->fileName = $fileName;        $this->loadFromDisk($fileName);
    }    public function display()
    {        print_r("Displaying ". $this->fileName);        echo &#39;<pre/>&#39;;
    }    private function loadFromDisk($fileName)
    {        print_r("Loading ". $fileName);        echo &#39;<pre/>&#39;;
    }
}

(3)ProxyImage.class.php(代理类)

<?php

namespace Proxy;class ProxyImage implements Image
{    private $realImage;    private $fileName;    
public function __construct($fileName)
    {        $this->fileName = $fileName;
    }    public function display()
    {        if ($this->realImage == null){            
    $this->realImage = new RealImage($this->fileName);
        }        return $this->realImage->display();
    }
}

(4)proxy.php

3b7462c1ecb9e636460d764deddddf92

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

PHP中的操作mysqli的预处理prepare

单例模式连接数据库的方法

以上是php實作代理模式的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn