1.概述

因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ? 你有想过限制访问某个对象,也就是说,提供一组方法给普通用户,特别方法给管理员用户?以上两种需求都非常类似,并且都需要解决一个更大的问题:你如何提 供一致的接口给某个对象让它可以改变其内部功能,或者是从来不存在的功能? 可以通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象的一个替身。即代理对象。它可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务

例子1:经典例子就是网络代理,你想访问facebook或者twitter ,如何绕过GFW,找个代理网站。

例子2:可以调用远程代理处理一些操作如图:

2.问题:

你怎样才能在不直接操作对象的情况下,对此对象进行访问?

3.解决方案

代理模式:为其他对象提供一种代理,并以控制对这个对象的访问。(Provide asurrogate or placeholder foranother object tocontrol access to it. )而对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。代理可以提供延迟实例化(lazy instantiation),控制访问, 等等,包括只在调用中传递。 一个处理纯本地资源的代理有时被称作虚拟代理。远程服务的代理常常称为远程代理。强制 控制访问的代理称为保护代理。

4.实用性

在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy模式。下面是一些可以使用Proxy模式常见情况:
1) 远程代理(Remote  Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)
2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 
3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
5) Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

5. 结构

Uml图:

简单结构示意图:

6.模式的组成

1)代理角色(Proxy):
. 保存一个引用使得代理可以访问实体。若 RealSubject和Subject的接口相同,Proxy会引用Subject。
. 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。
. 控制对实体的存取,并可能负责创建和删除它。
. 其他功能依赖于代理的类型:
• Remote Proxy负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求。
• Virtual Proxy可以缓存实体的附加信息,以便延迟对它的访问。
• Protection Proxy检查调用者是否具有实现一个请求所必需的访问权限。
2) 抽象主题角色(Subject):定义真实主题角色RealSubject
和 抽象主题角色Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使
用Proxy。代理主题通过持有真实主题RealSubject的引用,不但可以控制真实主题RealSubject的创建或删除,可以在真实主题RealSubject被调用前进行拦截,或在调用后进行某些操作.

3) 真实主题角色(RealSubject):定义了代理角色(proxy)所代表的具体对象.

7. 效果

Proxy模式在访问对象时引入了一定程度的间接性。根据代理的类型,附加的间接性有多种用途:
1) Remote Proxy可以隐藏一个对象存在于不同地址空间的事实。也使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
2) Virtual Proxy 可以进行最优化,例如根据要求创建对象。即通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗。
3) Protection Proxies和Smart Reference都允许在访问一个对象时有一些附加的内务处理(Housekeeping task) 。

Proxy模式还可以对用户隐藏另一种称之为写时复制(copy-on-write)的优化方式,该优化与根据需要创建对象有关。拷贝一个庞大而复杂的对象是一种开销很大的操作,如果这个拷贝根本没有被修改,那么这些开销就没有必要。用代理延迟这一拷贝过程,我们可以保证只有当这个对象被修改的时候才对它进行拷贝。在实现copy-on-write时必须对实体进行引用计数。拷贝代理仅会增加引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正的拷贝它。在这种情况下,代理还必须减
少实体的引用计数。当引用的数目为零时,这个实体将被删除。copy-on-write可以大幅度的降低拷贝庞大实体时的开销。

代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。

代理模式的缺点
由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

8.实现

我们用获取天气预报的例子说明代理模式:

    <?php
/**
* 代理模式
*
* 为其他对象提供一个代理以控制这个对象的访问
*
*/
/**
* 抽象主题角色(Subject):天气
*
*/
interface Weather
{
public function request($city);
public function display($city);
public function isValidCity($city); } /**
* 真实主题角色(RealSubject):
*
*/
class RealWeather implements Weather
{
protected $_url = 'http://www.google.com/ig/api?&oe=utf-8&hl=zh-cn&weather=';
protected $_weatherXml = '' ;
function __construct(){ } public function request($city){
$this->_weatherXml = file_get_contents($this->_url . $city );
}
public function display($city ){
if ($this->_weatherXml == '') {
$this->request($city);
}
//$this->_weatherXml = mb_convert_encoding($this->_weatherXml, 'UTF-8', 'GB2312');
$weatherxml = simplexml_load_string($this->_weatherXml);
$low = intval($weatherxml->weather->forecast_conditions[]->low->attributes());
$high = $weatherxml->weather->forecast_conditions[]->high->attributes();
$icon= 'http://www.google.com'. $weatherxml->weather->forecast_conditions[]->icon->attributes();
$condition=$weatherxml->weather->forecast_conditions[]->condition->attributes();
$weather = date('Y年n月j日').' 天气预报:<span class="cor_ff6c00 f_bold">'.$city_names[$city].' </span> <img class="v_middle" src="'.$icon.'" alt="'.$condition.'" width="16" height="17" align="absmiddle" /> <span class="f_bold"></span>: '.$low.'°C ~ '.$high.'°C '.$condition;
echo $weather;
} public function isValidCity($city){ } } /**
* 代理角色(Proxy):延迟代理
*
*/
class ProxyWeather implements Weather {
private $_client ;
private function client() {
if (! $this->_client instanceof RealWeather) {
$this->_client = new RealWeather();
}
return $this->_client; }
public function request($city){
$this->_client()->request($city);
} public function isValidCity($city) {
return $this->_client()->isValidCity($city);
} public function display($city) {
return $this->client()->display($city);
}
}
/**
* 代理角色(Proxy):动态代理
*
*/
class GenericProxyWeather { protected $_subject;
public function __construct($subject) {
$this->_subject = $subject;
} public function __call($method, $args) {
return call_user_func_array(
array($this->_subject, $method),
$args);
} } class Client{ static function main(){
$proxy = new ProxyWeather();
$report = $proxy->display('beijing');
}
static function Genericmain(){
$proxy = new GenericProxyWeather(new RealWeather());
$report = $proxy->display('beijing');
}
}
header('Content-type:text/html;charset=UTF-8');
Client::main();
//Client::Genericmain();

9. 与其他相关模式

1)适配器模式Adapter:适配器Adapter 为它所适配的对象提供了一个不同的接口。相反,代理提供了与它的实体相同的接口。然而,用于访问保护的代理可能会拒绝执行实体会执行的操作,因此,它的接口实际上可能只是实体接口的一个子集。

2) 装饰器模式Decorator:尽管Decorator的实现部分与代理相似,但
Decorator的目的不一样。Decorator为对象添加一个或多个功能,而代理则控制对对象的访问。

10.总结

代理模式在很多情况下都非常有用,特别是你想强行控制一个对象的时候,比如:延迟加载,监视状态变更的方法等等

1、“增加一层间接层”是软件系统中对许多负责问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。

2、具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象作细粒度的控制,有些可能对组件模块提供抽象代理层,在架构层次对对象作proxy。

3、proxy并不一定要求保持接口的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。

本文章摘自 http://blog.csdn.net/hguisu/article/details/7542143

设计模式(十一)代理模式Proxy(结构型)的更多相关文章

  1. Java设计模式11:常用设计模式之代理模式(结构型模式)

    1. Java之代理模式(Proxy Pattern) (1)概述: 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象 ...

  2. 设计模式12: Proxy 代理模式(结构型模式)

    Proxy 代理模式(结构型模式) 直接与间接 人们对于复杂的软件系统常常有一种处理手法,即增加一层间接层,从而对系统获得一种更为灵活.满足特定需求的解决方案.如下图,开始时,A需要和B进行3次通信, ...

  3. 设计模式 笔记 代理模式 Proxy

    //---------------------------15/04/21---------------------------- //Proxy 代理模式-----对象结构型模式 /* 1:意图: ...

  4. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  5. 大熊君说说JS与设计模式之------代理模式Proxy

    一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...

  6. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...

  7. 结构型设计模式之代理模式(Proxy)

    结构 意图 为其他对象提供一种代理以控制对这个对象的访问. 适用性 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用P r o x y 模式.下面是一 些可以使用P r o x y 模式常见 ...

  8. Java基础-设计模式之-代理模式Proxy

    代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...

  9. [设计模式] 12 代理模式 proxy

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问.结合上面的游戏代理的例子和下面的图,我们来进行分析一下.以前你是这 ...

  10. c#设计模式之代理模式(Proxy Pattern)

    引言 代理这个词语,大家在现实世界已经频繁的接触过,例如火车站代理售票点,因为这些代理售票点的存在,我们不必要去火车站的售票处就可以查询或者取到火车票.代理点本身是没有能力生产车票的,我们在代理处享受 ...

随机推荐

  1. TraceView简单使用方法

    一.TraceView简介 TraceView是AndroidSDK里面自带的工具,用于对Android的应用程序以及Framework层的代码进行性能分析. TraceView是图形化的工具,最终它 ...

  2. ldap理论属于概念缩略词

    Standalone LDAP Daemon, slapd(standalone lightweight access protocol) ldap 389 default listener port ...

  3. kvm中运行kvm

    如何在 KVM 虚拟机上运行 KVM 上次讨论了如何在 VMware ESXi 虚拟机上运行 KVM 问题,前不久有读者想 “在 kvm 上面创建个虚拟机安装 rackspace 的 openstac ...

  4. 前端web应用组件化(一) 徐飞

    https://github.com/xufei/blog/issues/6 Web应用的组件化(一) 基本思路 1. 为什么要做组件化? 无论前端也好,后端也好,都是整个软件体系的一部分.软件产品也 ...

  5. C实例--推断一个字符串是否是回文数

    回文是指顺读和反读内容均同样的字符串.比如"121","ABBA","X"等. 本实例将编写函数推断字符串是否是回文. 引入两个指针变量,開 ...

  6. 黑马程序员_<<String类>>

    --------------------ASP.Net+Android+IOS开发..Net培训.期待与您交流! -------------------- 1. String类 1.概述 String ...

  7. SQL server 2008无法连接Local服务器的解决办法

    SQL的有些服务总是在关机的时候自动关闭,然后你可以打开 控制面板——管理工具——服务,然后找到SQL相关的服务,右键——属性,里面有设置,可以设成自动启动

  8. js 中的闭包

    /** *闭包就是在一个函数的外面访问函数内部的变量 **/ var name = "xiao A"; var obj = { name : "xiao B" ...

  9. CF 599D Spongebob and Squares(数学)

    题目链接:http://codeforces.com/problemset/problem/599/D 题意:定义F(n,m)为n行m列的矩阵中方阵的个数,比如3行5列的矩阵,3x3的方阵有3个.2x ...

  10. linux install nginx error

    1 2 3 4 5 6 7 8 9 10 11 [mahao01@127.0.0.1 nginx-1.2.9]$ make make -f objs/Makefile make[1]: Enterin ...