PHP设计模式之代理模式的深入解析


Posted in PHP onJune 13, 2013

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

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

PHP设计模式之代理模式的深入解析

代理模式的对象图与装饰模式对象图在结构上类似,但表达的目的各有不同,装饰者给对象动态增加行为,而代理则控制来自客户端的访问。此外,代理只在需要时才创建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 ';  
    }  
}  
$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初学者头疼问题总结
Jul 08 PHP
用PHP和ACCESS写聊天室(四)
Oct 09 PHP
PHP模块 Memcached功能多于Memcache
Jun 14 PHP
PHP设计模式之装饰者模式
Feb 29 PHP
php中防止SQL注入的最佳解决方法
Apr 25 PHP
php 创建以UNIX时间戳命名的文件夹(示例代码)
Mar 08 PHP
ASP和PHP实现生成网站快捷方式并下载到桌面的方法
May 08 PHP
THINKPHP支持YAML配置文件的设置方法
Mar 17 PHP
php获取百度收录、百度热词及百度快照的方法
Apr 02 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
Sep 23 PHP
PHP简单实现遍历目录下特定文件的方法小结
May 22 PHP
Laravel学习教程之IOC容器的介绍与用例
Aug 15 PHP
PHP设计模式之责任链模式的深入解析
Jun 13 #PHP
PHP设计模式之结构模式的深入解析
Jun 13 #PHP
PHP设计模式之命令模式的深入解析
Jun 13 #PHP
深入Memcache的Session数据的多服务器共享详解
Jun 13 #PHP
探讨:如何使用PHP实现计算两个日期间隔的年、月、周、日数
Jun 13 #PHP
判断php数组是否为索引数组的实现方法
Jun 13 #PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
Jun 13 #PHP
You might like
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
Zend Framework基本页面布局分析
2016/03/19 PHP
tp5框架使用cookie加密算法实现登录功能示例
2020/02/10 PHP
js 判断 enter 事件
2009/02/12 Javascript
Jquery练习之表单验证实现代码
2010/12/14 Javascript
jquery随意添加移除html的实现代码
2011/06/21 Javascript
jQuery截取指定长度字符串代码
2014/08/21 Javascript
一个获取第n个元素节点的js函数
2014/09/02 Javascript
iframe跨域通信封装详解
2015/08/11 Javascript
jquery使用ul模拟select实现表单美化的方法
2015/08/18 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
jQuery解决$符号命名冲突
2016/06/18 Javascript
微信小程序点击控件修改样式实例详解
2017/07/07 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
2017/10/12 Javascript
js将键值对字符串转为json字符串的方法
2018/03/30 Javascript
使用Angular CLI快速创建Angular项目的一些基本概念和写法小结
2018/04/22 Javascript
详解基于Vue-cli搭建的项目如何和后台交互
2018/06/29 Javascript
VUE+elementui面包屑实现动态路由详解
2019/11/04 Javascript
vue项目中在可编辑div光标位置插入内容的实现代码
2020/01/07 Javascript
微信小程序实现聊天室
2020/08/21 Javascript
python输出当前目录下index.html文件路径的方法
2015/04/28 Python
浅谈Python中的数据类型
2015/05/05 Python
Python验证码识别的方法
2015/07/10 Python
python入门基础之用户输入与模块初认识
2016/11/14 Python
Python网络爬虫中的同步与异步示例详解
2018/02/03 Python
Python绘制热力图示例
2019/09/27 Python
Python Numpy中数据的常用保存与读取方法
2020/04/01 Python
PyCharm Ctrl+Shift+F 失灵的简单有效解决操作
2021/01/15 Python
意大利比基尼品牌:MISS BIKINI
2019/11/02 全球购物
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
测试工程师职业规划书
2014/02/06 职场文书
元旦联欢会主持词
2014/03/26 职场文书
交通安全标语
2014/06/06 职场文书
校车安全责任书
2014/08/25 职场文书
2015年城管执法工作总结
2015/07/23 职场文书
请病假条范文
2015/08/17 职场文书