這篇文章主要介紹了關於php中如何透過虛擬代理實現延遲加載,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
基本原理是透過一個虛代理(Virtual Proxy)做佔位符,一旦存取代理物件的某成員(方法或屬性),載入就被觸發。
此貨是從 Martin 大神的《企業應用架構模式》中學到的,輔助 PHP 動態語言的特性,可以比 Java 輕鬆很多的實現延遲加載(LazyLoad)。基本原理是透過一個虛擬代理(Virtual Proxy)做佔位符,一旦存取代理物件的某成員(方法或屬性),載入就會被觸發。
不過我實現的這個版本有限制:
只適用於對象,無法代理數組等基本資料類型(需要用ArrayObject 一類的內建對象封裝)
被代理之後,有些有操作符重載性質的介面實作就失效了,例如ArrayAccess 的索引器、Itreator 的迭代器,如果是用該代理來處理集合類型的延遲加載,還需要繼承一個子類做特殊處理,以便外部用foreach 迭代
// 测试 $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中如何透過虛擬代理實現延遲加載的詳細內容。更多資訊請關注PHP中文網其他相關文章!