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 相关文章推荐
PHP中cookies使用指南
Mar 16 PHP
php.ini 配置文件的深入解析
Jun 17 PHP
thinkphp路由规则使用示例详解和伪静态功能实现(apache重写)
Feb 24 PHP
PHP.ini中配置屏蔽错误信息显示和保存错误日志的例子
May 12 PHP
PHP生成RSS文件类实例
Dec 05 PHP
PHP实现懒加载的方法
Mar 07 PHP
PHP实现C#山寨ArrayList的方法
Jul 16 PHP
smarty学习笔记之常见代码段用法总结
Mar 19 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
Feb 17 PHP
PHP 传输会话curl函数的实例详解
Sep 12 PHP
PHP实现的mysql读写分离操作示例
May 22 PHP
Laravel中10个有用的用法小结
May 06 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
新版PHP极大的增强功能和性能
2006/10/09 PHP
PHP图片库imagemagick安装方法
2014/09/23 PHP
PHP数据对象PDO操作技巧小结
2016/09/27 PHP
PHP通过文件路径获取文件名的实例代码
2018/10/14 PHP
仿服务器端脚本方式的JS模板实现方法
2007/04/27 Javascript
jQuery学习4 浏览器的事件模型
2010/02/07 Javascript
javascript面向对象之二 命名空间
2011/02/08 Javascript
在浏览器窗口上添加遮罩层的方法
2012/11/12 Javascript
jquery自定义属性(类型/属性值)
2013/05/21 Javascript
简介JavaScript中用于处理正切的Math.tan()方法
2015/06/15 Javascript
jquery实现带缩略图的全屏图片画廊效果实例
2015/06/25 Javascript
jquery Easyui快速开发总结
2015/08/20 Javascript
Angular2  NgModule 模块详解
2016/10/19 Javascript
详解Vue方法与事件
2017/03/09 Javascript
用 js 的 selection range 操作选择区域内容和图片
2017/04/18 Javascript
xmlplus组件设计系列之选项卡(Tabbar)(5)
2017/05/03 Javascript
如何使用pm2快速将项目部署到远程服务器
2019/03/12 Javascript
Node.js之readline模块的使用详解
2019/03/25 Javascript
通过微信公众平台获取公众号文章的方法示例
2019/12/25 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
2020/04/10 Javascript
python中assert用法实例分析
2015/04/30 Python
MySQL最常见的操作语句小结
2015/05/07 Python
Python基于Tkinter的HelloWorld入门实例
2015/06/17 Python
python 多个参数不为空校验方法
2019/02/14 Python
Django中提示消息messages的设置方式
2019/11/15 Python
Python绘制全球疫情变化地图的实例代码
2020/04/20 Python
python用什么编辑器进行项目开发
2020/06/17 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
2021/01/05 Python
小学数学课后反思
2014/04/23 职场文书
关于运动会的口号
2014/06/07 职场文书
优秀教师先进事迹材料
2014/12/15 职场文书
跳高加油稿
2015/07/21 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
话题作文之呼唤
2019/12/18 职场文书
mysql中数据库覆盖导入的几种方式总结
2022/03/25 MySQL
JavaScript原型链中函数和对象的理解
2022/06/16 Javascript