PHP设计模式漫谈之代理模式

原创
开发 后端 前端
PHP也有设计模式?是的,我们经常看到关于Java和.NET平台上设计模式的论述和讲解,其实,在PHP 5对面向对象的支持更加完善之后,设计模式的应用也可引入到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服务器的联系,代理在管理连接时可以完成其它任务,如访问控制和缓存大型下载文件。

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

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

参与者

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

主体(Subject):RealSubject的抽象;

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

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

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

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

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

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

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

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

关于设计模式的其他方面

我们知道了什么是设计模式以及PHP设计模式中的代理模式。这里还有一些关于设计模式的基本概念应该被熟知。

◆算法不能算是一种设计模式,因为算法主要是用来解决计算上的问题,而非设计上的问题。

◆面向对象设计模式通常以类别或物件来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类别或物件。

◆设计模式主要是使不稳定的依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。

◆并非所有的软件模式都是设计模式,设计模式特指软件设计层次上的问题。还有其它非设计模式的模式,如架构模式。 

我们会在下周继续为您连载《PHP设计模式漫谈》,敬请期待。

【编辑推荐】

  1. 钟胜辉谈PHP发展的现状和前景
  2. Java设计模式与应用浅谈
  3. 架构、框架、设计模式之间的关系简述
  4. 专题:PHP开发基础入门

 原文:Practical Php Patterns: Proxy

链接:http://giorgiosironi.blogspot.com/2010/02/practical-php-patterns-proxy.html

 

 

责任编辑:佚名 来源: 51CTO.com
相关推荐

2010-04-19 09:30:00

工厂模式PHP设计模式

2010-04-13 08:54:28

PHP设计模式命令模式

2010-04-08 09:27:04

PHP设计模式结构模式

2010-04-21 08:38:18

解释器模式PHP设计模式

2010-04-29 08:53:11

PHP迭代器模式

2010-04-01 09:10:03

PHP设计模式责任链模式

2010-05-06 08:44:37

调解者模式

2012-02-29 09:41:14

JavaScript

2012-01-13 15:59:07

2021-06-29 08:54:23

设计模式代理模式远程代理

2022-09-07 08:25:08

代理模式设计模式代码

2011-04-21 09:46:41

设计模式

2011-04-06 11:41:25

Java动态代理

2024-02-26 11:52:38

代理模式设计

2024-04-16 00:07:36

设计模式代理模式替身

2020-08-21 07:23:50

工厂模式设计

2022-11-30 17:05:33

代码程序场景

2021-06-09 08:53:34

设计模式策略模式工厂模式

2015-09-08 13:39:10

JavaScript设计模式

2023-09-04 13:14:00

装饰器设计模式
点赞
收藏

51CTO技术栈公众号