PHP設計模式之代理模式

代理模式(Proxy),它是对简单处理程序(或指针)的增强,用于引用一个对象:这个指针被代理(Proxy)对象取代,代理对象位于客户端(Client)和真实执行程序之间,指针有一个可被多个目标利用的钩子。

从技术上讲,这种模式在客户端和真实主体(RealSubject)之间插入一个代理对象,维护subject接口和用不同的方式委派它的方法。代理可以透明地做任何事情:懒散创建RealSubject或载入数据,与其它机器交换消息,写时复制策略等。这与HTTP代理有点类似,其客户端(如浏览器)和应用程序依赖于与HTTP服务器的联系,代理在管理连接时可以完成其它任务,如访问控制和缓存大型下载文件。

PHP设计模式中的代理模式
PHP设计模式中的代理模式示例

代理模式的对象图与装饰模式对象图在结构上类似,但表达的目的各有不同,装饰者给对象动态增加行为,而代理则控制来自客户端的访问。此外,代理只在需要时才创建RealSubject。 

参与者

客户端(Client):取决于主体(Subject)实现;

主体(Subject):RealSubject的抽象;

真实主体(RealSubject):完成代价高昂的工作或包含大量的数据;

代理(Proxy):为Client提供一个与Subject一致的引用,仅在需要时才创建RealSubject实例或与RealSubject实例通信。

下面是两个被广泛使用的代理模式例子:

1、对象-关系映射(Orms)在运行中创建代理作为实体类的子类,以实现懒散加载(虚拟代理),这个代理会覆盖所有实体方法,在前面追加一个载入程序,在方法被真正调用前不会包含任何数据,Orms代理支持对象间的双向关系,不用加载整个数据库,因为它们被置于当前加载对象图的边界。

2、Java RMI使用远程代理对象(远程代理),当它们的方法被调用时,代理序列化参数,执行网络上的请求,委托调用另一个节点上的真实对象,这种技术允许透明地调用远程对象,不用担心它们是否在同一台机器上,但这种透明度很容易会使执行速度变慢。

下面的代码示例实现了一个ImageProxy,推迟了图像数据的加载。

 
 
  1. <?php  
  2. /**  
  3.  * Subject interface.  
  4.  * Client depends only on this abstraction.  
  5.  */ 
  6. interface Image  
  7. {  
  8.     public function getWidth();  
  9.  
  10.     public function getHeight();  
  11.  
  12.     public function getPath();  
  13.  
  14.     /**  
  15.      * @return string   the image's byte stream  
  16.      */ 
  17.     public function dump();  
  18. }  
  19.  
  20. /**  
  21.  * Abstract class to avoid repetition of boilerplate code in the Proxy  
  22.  * and in the Subject. Only the methods which can be provided without  
  23.  * instancing the RealSubject are present here.  
  24.  */ 
  25. abstract class AbstractImage implements Image  
  26. {  
  27.     protected $_width;  
  28.     protected $_height;  
  29.     protected $_path;  
  30.     protected $_data;  
  31.  
  32.     public function getWidth()  
  33.     {  
  34.         return $this->_width;  
  35.     }  
  36.  
  37.     public function getHeight()  
  38.     {  
  39.         return $this->_height;  
  40.     }  
  41.  
  42.     public function getPath()  
  43.     {  
  44.         return $this->_path;  
  45.     }  
  46. }  
  47.  
  48. /**  
  49.  * The RealSubject. Always loads the image, even if no dump of the data  
  50.  * is required.  
  51.  */ 
  52. class RawImage extends AbstractImage  
  53. {  
  54.     public function __construct($path)  
  55.     {  
  56.         $this->_path = $path;  
  57.         list ($this->_width, $this->_height) = getimagesize($path);  
  58.         $this->_data = file_get_contents($path);  
  59.     }  
  60.  
  61.     public function dump()  
  62.     {  
  63.         return $this->_data;  
  64.     }  
  65. }  
  66.  
  67. /**  
  68.  * Proxy. Defers loading the image data until it becomes really mandatory.  
  69.  * This class does its best to postpone the very expensive operations  
  70.  * such as the actual loading of the BLOB.  
  71.  */ 
  72. class ImageProxy extends AbstractImage  
  73. {  
  74.     public function __construct($path)  
  75.     {  
  76.         $this->_path = $path;  
  77.         list ($this->_width, $this->_height) = getimagesize($path);  
  78.     }  
  79.  
  80.     /**  
  81.      * Creates a RawImage and exploits its functionalities.  
  82.      */ 
  83.     protected function _lazyLoad()  
  84.     {  
  85.         if ($this->_realImage === null) {  
  86.             $this->_realImage = new RawImage($this->_path);  
  87.         }  
  88.     }  
  89.  
  90.     public function dump()  
  91.     {  
  92.         $this->_lazyLoad();  
  93.         return $this->_realImage->dump();  
  94.     }  
  95. }  
  96.  
  97. /**  
  98.  * Client class that does not use the data dump of the image.  
  99.  * Passing blindly a Proxy to this class and to other Clients makes sense  
  100.  * as the data would be loaded anyway when Image::dump() is called.  
  101.  */ 
  102. class Client  
  103. {  
  104.     public function tag(Image $img)  
  105.     {  
  106.         return '<IMG class=fit-image  SRC="'< span>$img->getPath() . '"  alt=""  width="' 
  107.              . $img->getWidth() . '"  height="'   
  108.              . $img->getHeight() . '"   >?< SPAN>;  
  109.     }  
  110. }  
  111.  
  112. $path = '/home/giorgio/shared/Immagini/kiki.png';  
  113. $client = new Client();  
  114.  
  115. $image = new RawImage($path); // loading of the BLOB takes place  
  116. echo $client->tag($image), "\n";  
  117.  
  118. $proxy = new ImageProxy($path);  
  119. echo $client->tag($proxy), "\n"// loading does not take place even here 

以上代码实现了PHP的代理模式。简单来讲,代理模式就是为其他对象提供一个代理以控制对这个对象的访问。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值