话说这货是从 Martin 大神的《企业应用架构模式》中学到的,辅助 PHP 动态语言的特性,可以比 Java 轻松很多的实现延迟加载――通过一个虚代理占位符.唯一的缺陷,是只能代理对象,不能代理内置基本类型.PHP编程
我试水的 PHP 领域模型设计中,也是用这个来实现 DomainObject 的延迟加载.PHP编程
?* 虚代理,只有在被拜访成员时才调用闭包函数生成目标对象.
?*
?* @author tonyseek
?*
?*/
class VirtualProxy
{
??? private $holder = null;
??? private $loader = null;
??? /**
???? * 虚代理,只有在被拜访成员时才调用闭包函数生成目标对象.
???? *
???? * @param Closure $loader 生成被代理对象的闭包函数
???? */
??? public function __construct(Closure $loader)
??? {
??????????? $this->loader = $loader;
??? }PHP编程
??? /**
???? * 代理成员方法的调用
???? *
???? * @param string $method
???? * @param array? $arguments
???? * @throws BadMethodCallException
???? * @return mixed
???? */
??? public function __call($method,array $arguments = null)
??? {
??????????? $this->check();PHP编程
??????????? if (!method_exists($this->holder,$method)) {
??????????????????? throw new BadMethodCallException();
??????????? }PHP编程
??????????? return call_user_func_array(
??????????????????? array(&$this->holder,$method),
??????????????????? $arguments);
??? }PHP编程
??? /**
???? * 代理成员属性的读取
???? *
???? * @param string $property
???? * @throws ErrorException
???? * @return mixed
???? */
??? public function __get($property)
??? {
??????????? $this->check();PHP编程
??????????? if (!isset($this->holder->$property)) {
??????????????????? throw new ErrorException();
??????????? }PHP编程
??????????? return $this->holder->$property;
??? }PHP编程
??? /**
???? * 代理成员属性的赋值
???? *
???? * @param string $property
???? * @param mixed? $value
???? */
??? public function __set($property,$value)
??? {
??????????? $this->check();PHP编程
??????????? $this->holder->$property = $value;
??? }PHP编程
??? /**
???? * 检查是否已经存在被代理对象,不存在则生成.
???? */
??? private function check()
??? {
??????????? if (null == $this->holder) {
??????????????????? $loader = $this->loader;
??????????????????? $this->holder = $loader();
??????????? }
??? }
}PHP编程
// 测试
$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);
PHP编程