php中通过虚代理实现延迟加载的实现代码


Posted in PHP onJune 10, 2011

这货是从 Martin 大神的《企业应用架构模式》中学到的,辅助 PHP 动态语言的特性,可以比 Java 轻松很多的实现延迟加载(LazyLoad)。基本原理是通过一个虚代理(Virtual Proxy)做占位符,一旦访问代理对象的某成员(方法或属性),加载就被触发。

不过我实现的这个版本有局限性:

只适用于对象,无法代理数组等基本数据类型(需要用 ArrayObject 一类的内置对象封装)
被代理之后,一些带有操作符重载性质的接口实现就失效了,例如 ArrayAccess 的索引器、Itreator 的迭代器,如果是用该代理来处理集合类型的延迟加载,还需要继承一个子类做特殊处理,以便外部用 foreach 迭代
demo

// 测试 
$v = new VirtualProxy(function(){ 
echo 'Now, Loading', "\n"; 
$a = new ArrayObject(range(1,100)); 
$a->abc = 'a'; 
// 实际使用中,这里调用的是 DataMapper 的 findXXX 方法 
// 返回的是领域对象集合 
return $a; 
}); 
// 代理对象直接当作原对象访问 
// 而此时构造方法传入的 callback 函数才被调用 
// 从而实现加载对象操作的延迟 
echo $v->abc . $v->offsetGet(50);

Virtual Proxy
/** 
* 虚代理,只有在被访问成员时才调用闭包函数生成目标对象。 
* 
* @author tonyseek 
* 
*/ 
class VirtualProxy 
{ 
private $holder = null; 
private $loader = null; /** 
* 虚代理,只有在被访问成员时才调用闭包函数生成目标对象。 
* 
* @param Closure $loader 生成被代理对象的闭包函数 
*/ 
public function __construct(Closure $loader) 
{ 
$this->loader = $loader; 
} 
/** 
* 代理成员方法的调用 
* 
* @param string $method 
* @param array $arguments 
* @throws BadMethodCallException 
* @return mixed 
*/ 
public function __call($method, array $arguments = null) 
{ 
$this->check(); 
if (!method_exists($this->holder, $method)) { 
throw new BadMethodCallException(); 
} 
return call_user_func_array( 
array(&$this->holder, $method), 
$arguments); 
} 
/** 
* 代理成员属性的读取 
* 
* @param string $property 
* @throws ErrorException 
* @return mixed 
*/ 
public function __get($property) 
{ 
$this->check(); 
if (!isset($this->holder->$property)) { 
throw new ErrorException(); 
} 
return $this->holder->$property; 
} 
/** 
* 代理成员属性的赋值 
* 
* @param string $property 
* @param mixed $value 
*/ 
public function __set($property, $value) 
{ 
$this->check(); 
$this->holder->$property = $value; 
} 
/** 
* 检查是否已经存在被代理对象,不存在则生成。 
*/ 
private function check() 
{ 
if (null == $this->holder) { 
$loader = $this->loader; 
$this->holder = $loader(); 
} 
} 
}
PHP 相关文章推荐
使用php4加速网络传输
Oct 09 PHP
PHP 字符串加密函数(在指定时间内加密还原字符串,超时无法还原)
Apr 28 PHP
php设计模式 Interpreter(解释器模式)
Jun 26 PHP
php多种形式发送邮件(mail qmail邮件系统 phpmailer类)
Jan 22 PHP
PHP5各个版本的新功能和新特性总结
Mar 16 PHP
PHP判断是否连接上网络的方法
Jul 01 PHP
PHP设置头信息及取得返回头信息的方法
Jan 25 PHP
php实现图片上传并进行替换操作
Mar 15 PHP
PHP给文字内容中的关键字进行套红处理
Apr 12 PHP
创建无限极分类树型结构的简单方法
Jun 20 PHP
php简单读取.vcf格式文件的方法示例
Sep 02 PHP
PHP读取文件或采集时解决中文乱码
Mar 09 PHP
php获取后台Job管理的实现代码
Jun 10 #PHP
php下通过curl抓取yahoo boss 搜索结果的实现代码
Jun 10 #PHP
PHP缩略图等比例无损压缩,可填充空白区域补充色
Jun 10 #PHP
PHP网站备份程序代码分享
Jun 10 #PHP
php在页面中调用fckeditor编辑器的方法
Jun 10 #PHP
PHP中遍历stdclass object的实现代码
Jun 09 #PHP
IIS7.X配置PHP运行环境小结
Jun 09 #PHP
You might like
SSI指令
2006/11/25 PHP
FCKeditor添加自定义按钮
2008/03/27 PHP
学习使用curl采集curl使用方法
2012/01/11 PHP
PHP循环输出指定目录下的所有文件和文件夹路径例子(简单实用)
2014/05/10 PHP
Yii输入正确验证码却验证失败的解决方法
2017/06/06 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
2018/08/21 PHP
获取焦点时,利用js定时器设定时间执行动作
2010/04/02 Javascript
Node.js入门教程:在windows和Linux上安装配置Node.js图文教程
2014/08/14 Javascript
JavaScript数组函数unshift、shift、pop、push使用实例
2014/08/27 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
2015/12/04 Javascript
基于Jquery插件实现跨域异步上传文件功能
2016/04/26 Javascript
jQuery实现页面滚动时智能浮动定位
2017/01/08 Javascript
使用vue实现简单键盘的示例(支持移动端和pc端)
2017/12/25 Javascript
解析vue、angular深度作用选择器
2019/09/11 Javascript
解决layui页面按钮点击无反应,也不报错的问题
2019/09/29 Javascript
Openlayers学习之地图比例尺控件
2020/09/28 Javascript
JavaScript 实现继承的几种方式
2021/02/19 Javascript
[02:41]DOTA2英雄基础教程 冥魂大帝
2014/01/16 DOTA
[59:26]DOTA2上海特级锦标赛D组资格赛#1 EG VS VP第二局
2016/02/28 DOTA
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
Python利用ElementTree模块处理XML的方法详解
2017/08/31 Python
python事件驱动event实现详解
2018/11/21 Python
Python 如何操作 SQLite 数据库
2020/08/17 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
基于CSS3实现的黑色个性导航菜单效果
2015/09/14 HTML / CSS
学前班教师的自我鉴定
2013/12/05 职场文书
优秀辅导员事迹材料
2014/02/16 职场文书
小学班主任评语大全
2014/04/23 职场文书
活动总结的格式
2014/05/07 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
2014年学生管理工作总结
2014/12/20 职场文书
三下乡个人总结
2015/03/04 职场文书
雷锋的观后感
2015/06/10 职场文书
MySQL触发器的使用
2021/05/24 MySQL
mysql主从复制的实现步骤
2021/10/24 MySQL
Go语言grpc和protobuf
2022/04/13 Golang