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下尝试使用GraphicsMagick的缩略图功能
Jan 01 PHP
PHP 5.3 下载时 VC9、VC6、Thread Safe、Non Thread Safe的区别分析
Mar 28 PHP
php学习笔记 PHP面向对象的程序设计
Jun 13 PHP
30 个很棒的PHP开源CMS内容管理系统小结
Oct 14 PHP
使用PHPMyAdmin修复论坛数据库的图文方法
Jan 09 PHP
PHP函数in_array()使用详解
Aug 20 PHP
最新制作ThinkPHP3.2.3完全开发手册
Nov 23 PHP
验证token、回复图文\文本、推送消息的实用微信类php代码
Jun 28 PHP
PHP实现批量重命名某个文件夹下所有文件的方法
Sep 04 PHP
kindeditor 加入七牛云上传的实例讲解
Nov 12 PHP
yii2的restful api路由实例详解
May 14 PHP
PHP过滤器 filter_has_var() 函数用法实例分析
Apr 23 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
php无限极分类实现的两种解决方法
2013/04/28 PHP
php新浪微博登录接口用法实例
2014/12/23 PHP
php删除文本文件中重复行的方法
2015/04/28 PHP
curl和libcurl的区别简介
2015/07/01 PHP
CentOS7.0下安装PHP5.6.30服务的教程详解
2018/09/29 PHP
js字符编码函数区别分析
2011/12/28 Javascript
深入理解JavaScript系列(6) 强大的原型和原型链
2012/01/15 Javascript
Jquery实现图片放大镜效果的思路及代码(自写)
2013/10/18 Javascript
jquery将一个表单序列化为一个对象的方法
2014/01/03 Javascript
JQuery select(下拉框)操作方法汇总
2015/04/15 Javascript
简介JavaScript中POSITIVE_INFINITY值的使用
2015/06/05 Javascript
深入理解Java线程编程中的阻塞队列容器
2015/12/07 Javascript
Node.js爬取豆瓣数据实例分析
2018/03/05 Javascript
jQuery实现炫丽的3d旋转星空效果
2018/07/04 jQuery
Vue与Node.js通过socket.io通信的示例代码
2018/07/25 Javascript
从Vuex中取出数组赋值给新的数组,新数组push时报错的解决方法
2018/09/18 Javascript
原生js实现公告滚动效果
2021/01/10 Javascript
浅谈Node 异步IO和事件循环
2019/05/05 Javascript
JS Generator 函数的含义与用法实例总结
2020/04/08 Javascript
vue中watch的用法汇总
2020/12/28 Vue.js
[02:43]DOTA2英雄基础教程 半人马战行者
2014/01/13 DOTA
python使用PyV8执行javascript代码示例分享
2013/12/04 Python
Python类属性与实例属性用法分析
2015/05/09 Python
Python连接SQLServer2000的方法详解
2017/04/19 Python
python扫描proxy并获取可用代理ip的实例
2017/08/07 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
详解python tkinter教程-事件绑定
2019/03/28 Python
解决Jupyter NoteBook输出的图表太小看不清问题
2020/04/16 Python
Python实现Canny及Hough算法代码实例解析
2020/08/06 Python
Tomcat中怎么使用log4j输出所有的log
2016/07/07 面试题
艺术系大学生毕业个人自我评价
2013/09/19 职场文书
物流司机岗位职责
2013/12/28 职场文书
2014年大班元旦活动方案
2014/02/26 职场文书
2014年两会学习心得范例
2014/03/17 职场文书
《桂花雨》教学反思
2014/04/12 职场文书
法制宣传教育方案
2014/05/09 职场文书