zoukankan      html  css  js  c++  java
  • Proxy模式

    本文完整翻译自http://giorgiosironi.blogspot.com/2010/02/practical-php-patterns-proxy.html

    因为搜到网上很多这个文章,最后的代码缺少了很大一部分,而且我在原文基础上,添加了memory_get_usage()使例子更方便理解

    代理模式(Proxy),它是对简单处理程序(或指针)的增强,用于引用一个对象:这个指针被代理(Proxy)对象取代,代理对象位于客户端(Client)和真实执行程序之间,指针有一个可被多个目标利用的钩子。

           从技术上讲,这种模式在客户端和真实主体(RealSubject)之间插入一个代理对象,维护subject接口和用不同的方式委派它的方法。代理可以透明地做任何事情:懒散创建RealSubject或载入数据,与其它机器交换消息,写时复制策略等。这与HTTP代理有点类似,其客户端(如浏览器)和应用程序依赖于与HTTP服务器的联系,代理在管理连接时可以完成其它任务,如访问控制和缓存大型下载文件。

           

           代理模式的对象图与装饰模式对象图在结构上类似,但表达的目的各有不同,装饰者给对象动态增加行为,而代理则控制来自客户端的访问。此外,代理只在需要时才创建RealSubject。 

           参与者

           ◆客户端(Client):取决于主体(Subject)实现;

           ◆主体(Subject):RealSubject的抽象;

           ◆真实主体(RealSubject):完成代价高昂的工作或包含大量的数据;

           ◆代理(Proxy):为Client提供一个与Subject一致的引用,仅在需要时才创建RealSubject实例或与RealSubject实例通信。

           下面是两个被广泛使用的代理模式例子:

           1、对象-关系映射(Orms)在运行中创建代理作为实体类的子类,以实现懒散加载(虚拟代理),这个代理会覆盖所有实体方法,在前面追加一个载入程序,在方法被真正调用前不会包含任何数据,Orms代理支持对象间的双向关系,不用加载整个数据库,因为它们被置于当前加载对象图的边界。

           2、Java RMI使用远程代理对象(远程代理),当它们的方法被调用时,代理序列化参数,执行网络上的请求,委托调用另一个节点上的真实对象,这种技术允许透明地调用远程对象,不用担心它们是否在同一台机器上,但这种透明度很容易会使执行速度变慢。

           下面的代码示例实现了一个ImageProxy,推迟了图像数据的加载

    /**
     * 主体接口
     * 客户端只通过这个类来实现
     */
    interface Image
    {
        public function getWidth();
        public function getHeight();
        public function getPath();
    
        /**
         * @return string 图片的字节流
         */
        public function dump();
    }
    
    /**
     * 抽象类避免代理和主体类重复同样的代码
     * 这里只提供不需要实例化真正主体的方法。
     * (翻译自下面这句话,感觉翻译的不好,大家可以自行体会下)
     * Only the methods which can be provided without instancing
     * the RealSubject are present here.
     */
    abstract class AbstractImage implements Image
    {
        protected $_width;
        protected $_height;
        protected $_path;
        protected $_data;
    
        public function getHeight()
        {
            return $this->_height;
        }
    
        public function getWidth()
        {
            return $this->_width;
        }
    
        public function getPath()
        {
            return $this->_path;
        }
    }
    
    /**
     * 真正的主体,总会加载图片_data,即使不使用dump()方法
     */
    class RawImage extends AbstractImage
    {
        public function __construct($path)
        {
            $this->_path=$path;
            list($this->_width,$this->_height)=getimagesize($path);
            $this->_data=file_get_contents($path);
        }
    
        public function dump()
        {
            return $this->_data;
        }
    }
    
    /**
     * 代理类,延迟加载图片_data。直到被要求加载时候,才会进行加载
     * 推迟了加载BLOB这类数据的高昂代价。
     */
    class ImageProxy extends  AbstractImage
    {
        public function __construct($path)
        {
            $this->_path=$path;
            list($this->_width,$this->_height)=getimagesize($path);
        }
    
        /**
         * 实例化RawImage并调用其方法
         */
        protected function _lazyLoad(){
            if($this->_realImage==null){
                $this->_realImage=new RawImage($this->_path);
            }
        }
    
        public function dump()
        {
            $this->_lazyLoad();
            return $this->_realImage->dump();
        }
    }
    
    /**
     * 客户端类,不使用dump()方法。
     * 通过传入一个代理到此类或者其他客户端就可以使用了,
     * 当需要加载data时候去调用Image::dump()
     * 这句话也不是很好翻译,原文为:
     * Passing blindly a Proxy to this class and to other Clients makes sense
     * as the data would be loaded anyway when Image::dump() is called.
     */
    class client
    {
        public function tag(Image $img){
            return '<img src="' . $img->getPath() . '" alt="" width="'
            . $img->getWidth() . '" height="'
            . $img->getHeight() . '" />';
        }
    }
    
    $path='pentakill.jpg';
    $client=new client();
    echo memory_get_usage();//244048
    echo '<hr/>';
    
    $proxy=new ImageProxy($path);//并没有加载BLOB文件
    echo $client->tag($proxy);
    echo memory_get_usage();//244600
    echo '<hr/>';
    
    $image=new RawImage($path);//加载BLOB文件
    echo $client->tag($image);
    echo memory_get_usage();//752592

    以上代码实现了PHP的代理模式。简单来讲,代理模式就是为其他对象提供一个代理以控制对这个对象的访问。

    希望有大神看完以后,能翻译帮忙更好的翻译一下上面两句话 : )

  • 相关阅读:
    HackingLab-据说MD5加密很安全,真的是么
    HackingLab-猜猜这是经过了多少次加密
    MySQL8.0安装
    fastdfs 单节点部署多目录
    关于ssh密钥配置还需要输入密码的终极解决办法
    VMware 配置虚拟机NAT 方式上网
    redis bind的正确配置
    filebeat修改索引名字
    zabbix-server卡死不动
    ssh免秘钥快速配对。
  • 原文地址:https://www.cnblogs.com/leekale/p/5743082.html
Copyright © 2011-2022 走看看