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简单封装了一些常用JS操作
Feb 25 PHP
基于PHP文件操作的详解
Jun 05 PHP
php函数指定默认值方法的小例子
Dec 04 PHP
什么是OneThink oneThink后台添加插件步骤
Apr 13 PHP
SAE实时日志接口SDK用法示例
Oct 09 PHP
php实现与python进行socket通信的方法示例
Aug 30 PHP
PHP简单实现循环链表功能示例
Nov 10 PHP
php实现的AES加密类定义与用法示例
Jan 29 PHP
PHP实现的DES加密解密类定义与用法示例
Nov 02 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
Apr 15 PHP
laravel使用数据库测试注意事项
Apr 10 PHP
php封装实现钉钉机器人报警接口的示例代码
Aug 08 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遍历文件夹和文件列表示例分享
2014/03/11 PHP
smarty模板的使用方法实例分析
2019/09/18 PHP
PHP实现微信公众号验证Token的示例代码
2019/12/16 PHP
JQuery 1.4 中的Ajax问题
2010/01/23 Javascript
ie下动态加态js文件的方法
2011/09/13 Javascript
getElementByIdx_x js自定义getElementById函数
2012/01/24 Javascript
功能强大的Bootstrap组件(结合js)
2016/08/03 Javascript
jQuery表单验证简单示例
2016/10/17 Javascript
javascript鼠标跟随运动3种效果(眼球效果,苹果菜单,方向跟随)
2016/10/27 Javascript
不使用script导入js文件的几种方法
2016/10/27 Javascript
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
2017/08/30 Javascript
详解angular笔记路由之angular-router
2017/09/12 Javascript
JavaScript实现焦点进入文本框内关闭输入法的核心代码
2017/09/20 Javascript
ES6中的Promise代码详解
2017/10/09 Javascript
Spring Boot/VUE中路由传递参数的实现代码
2018/03/02 Javascript
Angular6笔记之封装http的示例代码
2018/07/27 Javascript
JS轮播图的实现方法
2020/08/24 Javascript
[01:07]DOTA2次级职业联赛 - Fpb战队宣传片
2014/12/01 DOTA
[01:59]游戏“zheng”当时试玩会
2019/08/21 DOTA
python关键字and和or用法实例
2015/05/28 Python
python XlsxWriter模块创建aexcel表格的实例讲解
2018/05/03 Python
python 切换root 执行命令的方法
2019/01/19 Python
Python3环境安装Scrapy爬虫框架过程及常见错误
2019/07/12 Python
Python多线程多进程实例对比解析
2020/03/12 Python
Python SMTP配置参数并发送邮件
2020/06/16 Python
CSS3 选择器 基本选择器介绍
2012/01/21 HTML / CSS
html5定位并在百度地图上显示的示例
2014/04/27 HTML / CSS
说出ArrayList,Vector, LinkedList的存储性能和特性
2015/01/04 面试题
写出SQL四条最基本的数据操作语句(DML)
2012/12/12 面试题
测量工程专业求职信
2014/02/24 职场文书
小学母亲节活动方案
2014/03/14 职场文书
行政专员求职信范文
2014/05/03 职场文书
研究生就业推荐表导师评语
2014/12/31 职场文书
护士2015年终工作总结
2015/04/29 职场文书
党支部意见范文
2015/06/02 职场文书
vue里使用create, mounted调用方法
2022/04/26 Vue.js