`

三十八:代理模式

阅读更多
一:什么是代理
代理模式给某一个对象提供一个代理对象,并由代理对象控制原对象的引用.
中国人是一个含蓄的民族,讲求微妙和间接的交流方式,对象间的间接通信也同样是面向对象的设计中一条重要的"审美观"。间接性的通信可以给出较低的耦合关系,较强的合作关系,以及微妙的结构和易于复用的设计架构。
代理模式的英文叫做Proxy,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动,在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户和目标之间起到中介的作用.
比如说Window的快捷方式(Shortcut)就是一个代理的例子,如果原对象被删除,则快捷方式虽然可以存在,但是在调用时会给出错误.

二:代理的种类
如果按使用的目的来划分,代理有以下几种:
(A)远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象,这个不同的地址空间可以是在本机器中,也可是在另一台机器中,远程代理又叫大使.
(B)虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建.
(C)保护(Protect)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限.
(D)智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来.
.....上面是最常用的代理,还有其他的种类,在此不作介绍.

三:代理模式的角色
(A)抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。
(B)代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象:代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体,控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或者之后,都要执行某个操作,而不是单纯地将调用传递给真实主题对象.
(C)真实主题角色:定义了代理角色所代理的真实对象.
下面是示意性的源码:

package cai.milenfan.basic.test; 
//抽象主题角色
abstract public class Subject { 
//申明一个抽象的请求方法
abstract public void request(); 
} 


package cai.milenfan.basic.test; 
//具体主题角色
public class RealSubject extends Subject{ 
public void request() { 
System.out.println("request from RealSubject........"); 
} 
} 



package cai.milenfan.basic.test; 

public class ProxySubject extends Subject{ 
private RealSubject realSubject; 
//请求前的操作
private void preRequest(){ 
//do something you want before the request... 
} 
public void request() { 
preRequest(); 
if(realSubject==null){ 
realSubject = new RealSubject(); 
} 
realSubject.request(); 
postRequest(); 
} 
private void postRequest(){ 
//do something you want after the request 
} 
} 


package cai.milenfan.basic.test; 
//客户端调用. 
public class TestProxy { 
public static void main(String[] args){ 
Subject subject = new ProxySubject(); 
subject.request(); 
} 
} 


代理模式将一个代理插入到客户端和主题角色之间,提供了较多的灵活性,如代理主题可以在向真实主题传递客户端的请求之前执行特定的操作,并决定是否将请求传递给真实主题,代理主题可以在向真实主题传递客户端请求后执行另外一种操作,比如将客户端请求计数.....

四:Java2.0对代理模式的支持
(A)反身映射(Reflection)与动态代理
自从JDK1.3以来,Java语言通过在java.lang.reflect库中提供下面三个类直接支持代理模式:Proxy,InvocationHandler和Method.其中Proxy类使得设计师能够在运行时间创建代理对象,当有一个代理对象后,对原对象的方法调用首先被分派给一个调用处理器(Invocation Handler),程序可以在处理器的invoke()方法里截获这个调用,进行额外的操作,Java所提供的这一支持是建立在反身映射(Reflection)的基础上的,设计师可以按照下面的步骤创建动态代理对象:
(1)指明一系列的接口来创建一个代理对象
(2)创建一个调用处理器(InvocationHandleer)对象
(3)将这个代理指定为某个其他对象的代理对象
(4)在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作.
下面给出一个例子,这个例子要解决的问题是为一个Vector对象提供一个代理对象,当Vector的任何方法被调用之前和之后,分别打印出两条信息,这表明代理对象有能力截获和控制这个Vecto对象,这里仅仅需要一个新的类,称为VectorProxy类,此类需要实现java.lang.reflectInvocationHandler,由于Vector对象实现了java.util.List接口,因此调用List的方法,可以操控代理对象,其源代码如下:
package cai.milenfan.basic.test; 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 
import java.util.List; 
import java.util.Vector; 
public class VectorProxy implements InvocationHandler{ 
private Object proxyobj; 
public VectorProxy(Object obj){ 
proxyobj = obj; 
} 
//静态工厂方法
public static Object factory(Object obj){ 
Class cls = obj.getClass(); 
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new VectorProxy(obj)); 
} 
//调用某个方法
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { 
System.out.println("before calling " method); 
if(args!=null){ 
for(int i=0;i<args.length;i ){ 
System.out.println(args[i] ""); 
} 
} 
Object o = method.invoke(proxyobj, args); 
System.out.println("after calling " method); 
return o; 
} 
public static void main(String[] args){ 
List v = null; 
v = (List)factory(new Vector()); 
v.add("Milenfan"); 
v.add("czy"); 
} 
} 


也就是说,代理对象截获了对Vector对象的所有调用,在将调用传递给Vector之前和之后,代理对象具有采取合适操作的灵活性,虽然这里代理对象所采取的操作不过就是打印两种信息.本例子的对象图如下:
客户端-->VectorProxy-->InvocationHandler-->Vector。
在此例子中使用了静态工厂方法factory(),负责创建出Proxy类的实例,它将创建实现的细节隐藏起来,这是简单工厂模式的应用.
客户端分辨不出代理主题对象与真实主题对象,这是代理模式的一个重要用意.

五:代理模式的实现
代理模式可能并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并且传入.
(A)与适配器模式的关系:这两种模式看上去很相像,它们都可视为一个对象提供一种前置的接口。但是,适配器模式的用意是要改变所考虑的对象的接口,而代理模式并不能改变所代理的对象的接口,在这一点上两个模式有明显的区别。
(B)与装饰模式的关系:装饰模式与所装饰的对象具有相同的接口,因此这两种模式也有可能混淆,但是,装饰模式应当为所装饰的对象提供增强功能,而代理模式对对象的使用施加控制,并不提供对象本身的增强功能。
(C)与门面模式的关系:有的时候,门面模式兼任代理的责任.
分享到:
评论

相关推荐

    Head First 设计模式 JAVA源码

    第十二讲:代理模式 第十三讲:外观模式 第十四讲:组合模式 第十五讲:桥接模式 第十六讲:适配器模式 第十七讲:解释器模式 第十八讲:中介者模式 第十九讲:职责链模式 第二十讲:迭代模式 第二十一讲:...

    三十种架构设计模式(上).pdf

    ### 三十种架构设计模式(上) #### 一、引言 随着软件工程的发展与进步,设计模式成为了软件开发人员不可或缺的一部分。它们是基于长期实践经验总结出来的通用解决方案,旨在帮助开发者解决常见问题并提高代码...

    Spring Cloud Reference Guide 文字版 ,英文

    知识点三十八:复合环境仓库(CompositeEnvironmentRepositories) 知识点三十九:自定义复合环境仓库(CustomCompositeEnvironmentRepositories) 知识点四十:属性覆盖(PropertyOverrides) 知识点四十一:安全...

    设计模式C++版

    (四)代理模式:代理模式为其他对象提供一种代理以控制对该对象的访问。代理可以增加额外的功能,如缓存、安全控制等,同时不影响原始对象的使用。 (五)工厂方法模式:它是工厂模式的一种,将对象的创建延迟到...

    二十二种设计模式.pdf

    十一、代理模式 十二、命令模式 十三、责任链模式 十四、解释器模式 十五、迭代器模式 十六、备忘录模式 十七、中介者模式 十八、状态模式 十九、观察者模式 二十、策略模式 二十一、模板方法模式 二十二、访问者...

    设计模式PPT.rar

    12第十二讲代理模式 13第十三讲外观模式 14第十四讲组合模式 15第十五讲桥接模式 16第十六讲适配器模式 17第十七讲解释器模式 18第十八讲中介者模式 19第十九讲职责链模式 20第二十讲迭代模式 21第二十一讲模板方法...

    guide_to_php_design_pattern_zh.pdf

    - 第十一章:代理模式 - 第十二章:外观模式 - 第十三章:享元模式 - 第十四章:策略模式 - 第十五章:模板方法模式 - 第十六章:迭代器模式 - 第十七章:观察者模式 - 第十八章:命令模式 - **翻译团队**:...

    PHP设计模式介绍.

    #### 第十一章:代理模式—间接访问的桥梁 代理模式是一种结构型设计模式,它为其他对象提供了一个代理或占位符,以便控制对这个对象的访问。代理模式通常用于延迟加载、远程调用、访问控制等场景,它在不改变原有...

    java设计模式解释

    远程代理模式中,客户端可以通过代理来访问远端服务器上的资源,而无需直接与服务器通信。 #### 十三、责任链模式(Chain of Responsibility) **定义:** 责任链模式是一种行为型设计模式,允许多个对象都有机会...

    第二十八章:Nginx应用详解及配置1

    【第二十八章:Nginx应用详解及配置1】 Nginx是一款由俄罗斯开发者Igor Sysoev创建的高性能HTTP和反向代理服务器,同时也支持IMAP/POP3/SMTP代理服务。Nginx以其出色的性能、稳定性以及对硬件资源的高效利用而闻名...

    C++设计模式

    (四)代理模式 9 (五)工厂方法模式 11 (六)原型模式 13 (七)模板方法模式 15 迪米特法则 16 (八)外观模式 16 (九)建造者模式(生成器模式) 19 (十)观察者模式 23 (十一)抽象工厂模式 28 (十二)...

    Head First Design Patterns(All in one).pdf

    13. **第十三章:现实世界中的模式:更好的生活模式** - 探讨了设计模式如何应用于现实生活中的问题。 - 分享了一些实用的设计模式案例研究。 14. **附录:剩余的模式** - 简要介绍了其他一些重要的设计模式。...

    设计模式PPT合集

    八、代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问。在Java中,代理模式可以用于远程调用、安全控制、缓存等场景。 九、适配器模式 适配器模式使两个不兼容的接口能够协同工作。在Java中,适配器...

    GOF-设计模式-Design Patterns-英文原版-高清-有目录-有页码

    #### 八、设计模式的应用总结 **设计模式的应用总结:** - **期望从设计模式获得的价值**:设计模式可以帮助开发者更高效地解决问题,提高代码质量和可维护性。 - **设计模式的历史简介**:介绍设计模式的发展历程...

    61条面向对象设计的经验原则

    **原则三十八:** 如果一个类依赖另一个类的信息,考虑通过接口或抽象类来间接获取所需数据。这有助于降低直接依赖所带来的风险。 **原则三十九:** 随着系统的增长,确保它的可扩展性和灵活性。设计时考虑到未来...

    设计模式C#版

    二十、代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问。代理模式相当于为对象提供了一个“代言人”,从而控制对原始对象的访问,达到某种目的。 二十一、享元模式 享元模式是一种结构型设计模式,...

    C#设计模式PDF 电子书

    代理模式为其他对象提供一种代理以控制对这个对象的访问。在C#中,可以使用接口或继承来创建动态代理,如System.Reflection.Emit命名空间下的动态类型生成。 五、装饰器模式(Decorator) 装饰器模式允许向一个对象...

    Java中的23种设计模式

    **定义**: 代理模式为某一个对象提供一个代理,并由代理对象控制对原对象的引用。 **优点**: - 将客户端与目标对象解耦; - 提供额外的功能,如日志、权限控制等。 **应用场景**: - 需要控制对一个对象的访问; - ...

    php设计模式介绍

    ... ... 《PHP设计模式介绍》第三章 工厂模式 ... ...《PHP设计模式介绍》第八章 迭代器模式 ...《PHP设计模式介绍》第十一章 章代理模式 《PHP设计模式介绍》第十二章 装饰器模式 《PHP设计模式介绍》第十三章 适配器模式

Global site tag (gtag.js) - Google Analytics