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 和 MySQL 开发的 8 个技巧
Oct 09 PHP
Linux下 php5 MySQL5 Apache2 phpMyAdmin ZendOptimizer安装与配置[图文]
Nov 18 PHP
PHP的mysqli_query参数MYSQLI_STORE_RESULT和MYSQLI_USE_RESULT的区别
Sep 29 PHP
PHP中isset与array_key_exists的区别实例分析
Jun 02 PHP
joomla组件开发入门教程
May 04 PHP
Yii2实现log输出到file及database的方法
Nov 12 PHP
thinkPHP5.0框架安装教程
Mar 25 PHP
PDO::query讲解
Jan 29 PHP
PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
May 08 PHP
Yii2 queue的队列使用详解
Jul 19 PHP
thinkPHP+LayUI 流加载实现功能
Sep 27 PHP
PHP与SQL语句写一句话木马总结
Oct 11 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学习之变量的使用
2011/05/29 PHP
Codeigniter校验ip地址的方法
2015/03/21 PHP
PHP获取客户端及服务器端IP的封装类
2016/07/21 PHP
laravel学习教程之关联模型
2016/07/30 PHP
PHP图片添加水印功能示例小结
2016/10/03 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
JS DOM 操作实现代码
2010/08/01 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
js 判断文件类型并控制表单提交示例代码
2013/11/14 Javascript
asm.js使用示例代码
2013/11/28 Javascript
javascript的创建多行字符串的7种方法
2014/04/29 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
使用node+vue.js实现SPA应用
2016/01/28 Javascript
详解如何将 Vue-cli 改造成支持多页面的 history 模式
2017/11/20 Javascript
vue2实现可复用的轮播图carousel组件详解
2017/11/27 Javascript
Vue在页面数据渲染完成之后的调用方法
2018/09/11 Javascript
Cookbook组件形式:优化 Vue 组件的运行时性能
2018/11/25 Javascript
介绍Python中的一些高级编程技巧
2015/04/02 Python
编写Python脚本把sqlAlchemy对象转换成dict的教程
2015/05/29 Python
ubuntu安装sublime3并配置python3环境的方法
2018/03/15 Python
详解Python正则表达式re模块
2019/03/19 Python
利用Python实现Json序列化库的方法步骤
2020/09/09 Python
世界领先的以旅馆为主的在线预订平台:Hostelworld
2016/10/09 全球购物
艺术用品:Arteza
2018/11/25 全球购物
Agoda中文官网:安可达(低价预订全球酒店)
2021/01/18 全球购物
数据管理员的自我评价分享
2013/11/15 职场文书
高级工程师岗位职责
2013/12/15 职场文书
《长城和运河》教学反思
2014/04/14 职场文书
优秀驾驶员先进事迹材料
2014/05/04 职场文书
安全生产一岗双责责任书
2014/07/28 职场文书
2015年安全月活动总结
2015/03/26 职场文书
导游词之凤凰古城
2019/10/22 职场文书
Python代码风格与编程习惯重要吗?
2021/06/03 Python
MySql子查询IN的执行和优化的实现
2021/08/02 MySQL
Python FuzzyWuzzy实现模糊匹配
2022/04/28 Python
vue如何在data中引入图片的正确路径
2022/06/05 Vue.js