参考http://blog.csdn.net/jianghuxiaoxiami/article/details/3403924

1.代理模式

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式一般涉及到的角色有:

抽象角色:声明真实对象和代理对象的共同接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

以下是《Java与模式》中的示例为例:

1.1 静态代理

[java] view plaincopy
  1. package staticproxy;
  2. /**
  3. * 抽象角色
  4. */
  5. public abstract class Subject {
  6. public abstract void request();
  7. }
[java] view plaincopy
  1. package staticproxy;
  2. /**
  3. * 真实的角色
  4. */
  5. public class RealSubject extends Subject {
  6. @Override
  7. public void request() {
  8. // TODO Auto-generated method stub
  9. }
  10. }
[java] view plaincopy
  1. package staticproxy;
  2. /**
  3. * 静态代理,对具体真实对象直接引用
  4. * 代理角色,代理角色需要有对真实角色的引用,
  5. * 代理做真实角色想做的事情
  6. */
  7. public class ProxySubject extends Subject {
  8. private RealSubject realSubject = null;
  9. /**
  10. * 除了代理真实角色做该做的事情,代理角色也可以提供附加操作,
  11. * 如:preRequest()和postRequest()
  12. */
  13. @Override
  14. public void request() {
  15. preRequest();  //真实角色操作前的附加操作
  16. if(realSubject == null){
  17. realSubject =  new RealSubject();
  18. }
  19. realSubject.request();
  20. postRequest();  //真实角色操作后的附加操作
  21. }
  22. /**
  23. *  真实角色操作前的附加操作
  24. */
  25. private void postRequest() {
  26. // TODO Auto-generated method stub
  27. }
  28. /**
  29. *  真实角色操作后的附加操作
  30. */
  31. private void preRequest() {
  32. // TODO Auto-generated method stub
  33. }
  34. }
[java] view plaincopy
  1. package staticproxy;
  2. /**
  3. *  客户端调用
  4. */
  5. public class Main {
  6. public static void main(String[] args) {
  7. Subject subject = new ProxySubject();
  8. subject.request();  //代理者代替真实者做事情
  9. }
  10. }

以卖房(Subject的request方法)为例,卖房者(RealSubject)想卖房,但是不想搞那么多麻烦事,不想天天招买房的骚扰,就委托中介(ProxySubject)去帮忙卖房,中介帮忙卖房,当然不会简单的卖房,可能还需要收取中介费(preRequest()和postRequest()方法)等等附加收费,最终买房者(客户端Main)买房,找到的是中介,不会与房主接触,与房主接触的是中介,买房者最终跟中介买房,完成操作。

这个是静态代理。真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。

动态代理,就相当于代理者不仅仅只是代理一个真实对象,也可以代理很多对象,而且对象是动态指定的。

1.2 动态代理

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Objectobj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static Class getProxyClass (ClassLoaderloader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。(参见文献3)

在使用动态代理类时,我们必须实现InvocationHandler接口

[java] view plaincopy
  1. package dynamicproxy;
  2. /**
  3. * 抽象角色
  4. * 这里应改为接口
  5. */
  6. public interface Subject {
  7. void request();
  8. }
[java] view plaincopy
  1. package dynamicproxy;
  2. /**
  3. * 真实的角色
  4. * 实现接口
  5. */
  6. public class RealSubject implements Subject {
  7. @Override
  8. public void request() {
  9. // TODO Auto-generated method stub
  10. }
  11. }
[java] view plaincopy
  1. package dynamicproxy;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. /**
  5. * 动态代理, 它是在运行时生成的class,在生成它时你必须提供一组interface给它, 然后该class就宣称它实现了这些interface。
  6. * 你当然可以把该class的实例当作这些interface中的任何一个来用。 当然啦,这个Dynamic
  7. * Proxy其实就是一个Proxy,它不会替你作实质性的工作, 在生成它的实例时你必须提供一个handler,由它接管实际的工作。
  8. */
  9. public class DynamicSubject implements InvocationHandler {
  10. private Object sub; // 真实对象的引用
  11. public DynamicSubject(Object sub) {
  12. this.sub = sub;
  13. }
  14. @Override
  15. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  16. System.out.println("before calling " + method);
  17. method.invoke(sub,args);
  18. System.out.println("after calling " + method);
  19. return null;
  20. }
  21. }
[java] view plaincopy
  1. package dynamicproxy;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Proxy;
  5. public class Main {
  6. public static void main(String[] args) throws Throwable {
  7. RealSubject rs = new RealSubject();
  8. InvocationHandler handler = new DynamicSubject(rs);
  9. Class cls = rs.getClass();
  10. //以下是分解步骤
  11. /*
  12. Class c = Proxy.getProxyClass(cls.getClassLoader(), cls.getInterfaces());
  13. Constructor ct = c.getConstructor(new Class[]{InvocationHandler.class});
  14. Subject subject =(Subject) ct.newInstance(new Object[]{handler});
  15. */
  16. //以下是一次性生成
  17. Subject subject = (Subject)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), handler);
  18. subject.request();
  19. }
  20. }

通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系

1.3.代理模式使用原因和应用方面

(1)授权机制不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限.

(2)某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.

举例两个具体情况:

如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片.

如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.

总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系.

(3)现实中,Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用

from: https://blog.csdn.net/liangbinny/article/details/18656791

Java设计模式之代理模式(Proxy)相关推荐

  1. 三国杀与设计模式之代理模式(Proxy)

    本人原博地址:http://blog.saymagic.cn/blog.php?id=17 三国杀案例:在五人局中,作为反贼的黄月英借黄忠的刀杀作为忠臣的夏侯惇,从这句话中我们可以总结出一个成语对不对 ...

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

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

  3. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  4. Java设计模式(三) -- 代理模式

    代理是一种设计模式,即通过代理对象访问目标对象,这样可以在目标对象实现的基础上,增强额外的功能,即扩展目标类的功能. 通常编程中存在一种思想,即不要随意修改别人的代码或者方法,所以代理就可以在不修改目 ...

  5. java设计模式之代理模式详解

    代理模式在Java中十分常见,有如Spring实现AOP而使用动态代理,更有RPC实现中使用的调用端调用的代理服务.代理模型除了是一种设计模式之外,它更是一种思维,所以探讨并深入理解这种模型是非常有必 ...

  6. 05、人人都会设计模式:代理模式--Proxy

    PS:转载请注明出处 作者: TigerChain 地址: http://www.jianshu.com/p/1b3b6b003032 本文出自 TigerChain 简书 人人都会设计模式 教程简介 ...

  7. java设计模式之代理模式多种写法(三)

    背景 代理模式属于结构型模式,代理模式也是我们开发中常用的设计模式之一,本次讲解以下几种代理模式的写法,希望可以帮助大家更快的理解代理模式,包括自己写一个动态代理的方法. 静态代理 package c ...

  8. 设计模式之代理模式(Proxy)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  9. Java 设计模式之代理模式

    1.静态代理 被代理对象和代理对象都要实现相同的接口或者继承相同的父类. 不需要修改被代理对象就可以实现对功能的扩展,缺点是如果接口发生变化,比如增加新方法,被代理对象和代理对象都需要维护. 1)首先 ...

最新文章

  1. R语言获取当前R版本(version)实战
  2. (双引号)与 ' '(单引号)的区别
  3. 使用CFURLCreateStringByAddingPercentEscapes进行URL编码
  4. 【计算机视觉】几个计算机视觉库
  5. HDU 4609 3-idiots(FFT)
  6. 反转!物联网火爆,程序员开发技能却有待加强?
  7. JavaScript-声明变量的关键字
  8. Java基础之不一样的方法重载!
  9. 从零开始的Python学习Episode 20——面向对象(3)
  10. SQL 经典练习题 + 答案
  11. 单应性变换(Homography)的学习与理解
  12. 年轻时代,噢,年轻时代
  13. React 应用程序中的内联样式完整指南
  14. 穷爸爸富爸爸里面说的“现金流游戏”靠谱吗?
  15. 奇偶校验c语言ascii,奇偶校验(parity check)
  16. Android之Keystore文件签名(获取查看apk签名)
  17. GLSL到HLSL参考
  18. Windows必备软件,大而全|2022版
  19. 【科普向】谁都能看懂的CRC(循环冗余校验)原理
  20. 威纶通触摸屏可以解密吗_不会游泳可以潜水吗?!体验深潜要注意什么?带你解密DSD...

热门文章

  1. ConcurrentHashMap实现原理--转载
  2. no awt in java.libary.path
  3. CML 2020 | 显式引入对分类标签的描述,如何提高文本分类的效果?
  4. nestjs CRUD
  5. 2017年度盘点:15个最流行的GitHub机器学习项目 By 机器之心2017年12月21日 15:23 在本文中,作者列出了 2017 年 GitHub 平台上最为热门的知识库,囊括了数据科学、机
  6. Java - Java集合中的快速失败Fail Fast 机制
  7. Apache ZooKeeper - 选举Leader源码流程深度解析
  8. MyBatis-14MyBatis动态SQL之【foreach】
  9. Linux-awk及内置变量
  10. 复习笔记(四)——C++内联函数