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扩展函数
Oct 09 PHP
强烈推荐:php.ini中文版(2)
Oct 09 PHP
PHP 中的一些经验积累
Oct 09 PHP
php守护进程 加linux命令nohup实现任务每秒执行一次
Jul 04 PHP
mysqli_set_charset和SET NAMES使用抉择及优劣分析
Jan 13 PHP
PHP中上传多个文件的表单设计例子
Nov 19 PHP
php实现MySQL数据库备份与还原类实例
Dec 09 PHP
php上传大文件失败的原因及应对策略
Oct 20 PHP
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
Jan 08 PHP
php根据数据id自动生成编号的实现方法
Oct 16 PHP
完美解决php 导出excle的.csv格式的数据时乱码问题
Feb 18 PHP
php解析非标准json、非规范json的方式实例
May 10 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生成UTF8文件的方法
2010/05/15 PHP
php版本的cron定时任务执行器使用实例
2014/08/19 PHP
PHP对象递归引用造成内存泄漏分析
2014/08/28 PHP
php微信公众平台开发之获取用户基本信息
2015/08/17 PHP
PHP实现可自定义样式的分页类
2016/03/29 PHP
php 中的closure用法详解
2017/06/12 PHP
PHP后期静态绑定实例浅析
2018/12/21 PHP
JavaScript中Object和Function的关系小结
2009/09/26 Javascript
js document.write()使用介绍
2014/02/21 Javascript
jQuery弹出层后禁用底部滚动条(移动端关闭回到原位置)
2016/08/29 Javascript
简单实现js无缝滚动效果
2017/02/05 Javascript
Webpack框架核心概念(知识点整理)
2017/12/22 Javascript
Vue-cli3项目配置Vue.config.js实战记录
2018/07/29 Javascript
使用js实现将后台传入的json数据放在前台显示
2018/08/06 Javascript
vue使用v-if v-show页面闪烁,div闪现的解决方法
2018/10/12 Javascript
JavaScript中的 new 命令
2019/05/22 Javascript
Nodejs监控事件循环异常示例详解
2019/09/22 NodeJs
flexible.js实现移动端rem适配方案
2020/04/07 Javascript
使用 Github Actions 自动部署 Angular 应用到 Github Pages的方法
2020/07/20 Javascript
如何在vue中使用HTML 5 拖放API
2021/01/14 Vue.js
[01:18]一目了然!DOTA2DotA快捷操作对比第一弹
2014/07/01 DOTA
python中mechanize库的简单使用示例
2014/01/10 Python
Python中使用logging模块代替print(logging简明指南)
2014/07/09 Python
python基础教程之基本数据类型和变量声明介绍
2014/08/29 Python
Python中使用items()方法返回字典元素对的教程
2015/05/21 Python
在python中利用GDAL对tif文件进行读写的方法
2018/11/29 Python
python实现给微信指定好友定时发送消息
2019/04/29 Python
python logging模块的使用总结
2019/07/09 Python
python中调试或排错的五种方法示例
2019/09/12 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
幼儿园小班评语大全
2014/04/17 职场文书
团委书记的竞聘演讲稿
2014/04/24 职场文书
博士生专家推荐信
2015/03/25 职场文书
学子宴致辞大全
2015/07/27 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
基于Redis的List实现特价商品列表功能
2021/08/30 Redis