------- android培训、java培训、期待与您交流! ----------

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

代理模式一般设计的对象包括:抽象角色(封装要实现的功能的抽象类或接口)、代理角色(客户端访问真实对象的中间层对象)和真实角色(代理角色所代表的真实对象,是我们最终要引用的对象)。

代理模式的特点:

1、代理类和真实类必须实现同一个接口,而且在代理类中的接口方法中会调用真实类的接口方法,并在调用前后完成对一些预处理和后续处理的功能,实现接口功能的扩展。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

2、通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,从而在设计上获得了更大的灵活性。

代理模式的分类:静态代理和动态代理。

一、静态代理:在创建代理类的时候,定义了一个保存真实类对象的属性,并通过构造函数或其他方式将真实类对象传入到代理类对象中,在代理类实现他们共同接口方法的过程中完成对真实类功能的扩展。如下例子:

class  ProxyDemo
{public static void main(String[] args) {//需要预先知道真实角色并创建对象,若有很多真实角色,则需要大量的代理完成,大量对象创建,效率降低,另外,如果事先不知道真实角色呢?这就需要动态代理了RealSubject rSubject=new RealSubject();ProxySubject proSubject=new ProxySubject(rSubject);proSubject.request();}
}
abstract class Subject
{abstract public void request();
}
class RealSubject extends Subject
{RealSubject(){}public void request(){System.out.println("RealSubjcet's resquest is called!");}
}
class ProxySubject extends Subject
{private RealSubject rSubject;ProxySubject(RealSubject rSubject){this.rSubject=rSubject;}public void request(){preRequest();rSubject.request();postRequest();}public void preRequest(){System.out.println("ProxySubject do something preprocessing...");}public void postRequest(){System.out.println("ProxySubject do something postprocessing...");}
}
运行结果:
<img src="data:image/png;base64,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" alt="" />
注意:该方式的弊端就是:1、必须要知道真实对象的类型,即在运行时已经创建了真实类的对象。2、如果有许多的真实类需要代理来实现的时候,该方式需要给每一个真实类建立一个代理类,扩展性太差会大大降低效率。由此产生了另外一个高效的代理模式——动态代理。
二、动态代理:<span style="color: rgb(73, 73, 73); font-family: simsun; font-size: 14px; line-height: 21px; background-color: rgb(254, 254, 254); ">JAVA自带的动态代理是基于java.lang.reflect.Proxy、java.lang.reflect.InvocationHandler两个类</span><span style="background-color: rgb(254, 254, 254); color: rgb(73, 73, 73); font-family: simsun; line-height: 21px; ">使用JAVA反射机制</span><span style="color: rgb(73, 73, 73); font-family: simsun; line-height: 21px; background-color: rgb(254, 254, 254); ">来完成的。<span style="font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; line-height: 18px; ">所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一 组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实 例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy, 它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工 作。</span></span>
<span style="color: rgb(73, 73, 73); font-family: simsun; line-height: 21px; background-color: rgb(254, 254, 254); "><span style="font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; line-height: 18px; "></span></span><h3 id="sec-5-1" style="font-size: 16px; margin-left: -6px; margin-right: 0px; padding: 1px 0px 1px 1px; color: rgb(43, 128, 76); font-family: 'trebuchet ms'; border-bottom-color: rgb(43, 128, 76); border-bottom-width: 1px; border-bottom-style: solid; border-left-color: rgb(43, 128, 76); border-left-width: 6px; border-left-style: solid; background-color: rgb(217, 234, 224); line-height: 1; background-image: url(http://images.cnblogs.com/cnblogs_com/csophys/368957/r_lightgreen.gif); ">java动态代理UML图</h3><div id="text-5-1" class="outline-text-3" style="font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; line-height: 18px; "><p style="margin: 10px auto; "><img class="machine" src="http://images.cnblogs.com/cnblogs_com/machine/446980/o_proxy-pattern-java1.png" alt="latex-table" width="400" style="border: 0px; " /></p><p style="margin: 10px auto; ">java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类的四个方法:</p><ol style="margin-left: 0px; margin-right: 0px; padding: 0px 0px 0px 50px; "><li style="list-style-type: decimal; ">Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理 类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽 象方法在代理类中动态实现。</li><li style="list-style-type: decimal; ">Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject。</li><li style="list-style-type: decimal; ">Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。</li><li style="list-style-type: decimal; ">Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个 代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。</li><li style="list-style-type: decimal; ">Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用 (可使用被代理类的在Subject接口中声明过的方法)。</li></ol></div>

具体的实现步骤包括以下四个部分:

1.通过实现InvocationHandler接口创建自己的调用处理器;

2.通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理类;

3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

eg:

1、真实类的实现清单

interface Subject
{public abstract void request();public abstract void request1();
}
interface Answering
{public abstract void answering();
}
class RealSubject implements Subject,Answering
{RealSubject(){}public void request(){System.out.println("Dynamic Proxy's realsubject request() running...");}public void request1(){System.out.println("Dynamic Proxy's realsubject request1() running...");}public void answering(){System.out.println("Dynamic Proxy's realsubject's AnsweringInterface answering() running...");}
}

2、代理类实现清单:

import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
class  DynamicProxy implements InvocationHandler
{private Object sub;DynamicProxy(){}DynamicProxy(Object obj){this.sub=obj;}public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{System.out.println( " before calling "  + method);method.invoke(sub,args);System.out.println( " after calling "  + method);return  null ;}
}

3、客户端应用代理类访问真实类对象的实例代码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
class DynamicProxyDemo
{public static void main(String[] args) {RealSubject rSub=new RealSubject();InvocationHandler ih=new DynamicProxy(rSub);Class cls=rSub.getClass();Subject sub=(Subject)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ih);Answering ans=(Answering)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ih);sub.request();ans.answering();System.out.println(Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()));}
}

运行结果:

黑马程序员——Java的代理模式相关推荐

  1. 黑马程序员-java高新技术-代理和类加载器

    ------- android培训. java培训.期待与您交流! ---------- 代理模式:为其他对象提供一种代理以控制对这个对象的访问.说白了就是,在一些情况下客户不想或不能直接引一个对象, ...

  2. 2023年黑马程序员Java学习路线图

    2023年Java学科免费学习资源放送40+套课程,超过600小时的内容! 在过去的一年里,为了帮助更多人线上充电,学会更多技能,黑马程序员举办了 150+ 场免费直播公开课,新增精品视频教程 80+ ...

  3. 黑马程序员Java零基础视频教程_下部(P135-P200)

    黑马程序员Java零基础视频教程_下部(P135-P200) 1 多线程 1.1 什么是多线程? 1.2 多线程的并发与并行 1.3 多线程的实现方式 1.3.1 继承Thread类的方式进行实现 1 ...

  4. 黑马程序员Java教程学习笔记(三)

    学习视频:https://www.bilibili.com/video/BV1Cv411372m 如侵权,请私信联系本人删除 文章目录 黑马程序员Java教程学习笔记(三) 面向对象:设计对象.注意事 ...

  5. 黑马程序员——Java字符流、字节流IO流

    黑马程序员--Java字符流.字节流Io流 ---------------------- <a href="http://www.itheima.com"target=&qu ...

  6. 黑马 程序员——Java基础---流程控制

    黑马程序员--Java基础---流程控制 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java提供了两种基本的流程控制结构:分支结构 ...

  7. 黑马 程序员——Java基础---IO(下)

    黑马程序员--Java基础---IO(下) ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供 ...

  8. 黑马程序员Java教程学习笔记(五)

    学习视频:https://www.bilibili.com/video/BV1Cv411372m 如侵权,请私信联系本人删除 文章目录 黑马程序员Java教程学习笔记(五) 日期时间:Date.Sim ...

  9. 黑马程序员 JAVA WEB 第三节 MYSQL 约束

    这是阿锃总结的第三节黑马程序员JAVA WEB视频的MYSQL约束部分的笔记.希望可以帮助跟我一样正在学习Java web的同学们.我们一起进步.   b_d 若果有同学也想学习黑马程序员Java w ...

最新文章

  1. 【 FPGA 】门控时钟专题
  2. kali 树莓派 android,【原】树莓派安装KALI LINUX的手记
  3. ionic 混合应用开发
  4. HDMI高清光端机产品介绍
  5. java学习(34):巩固练习
  6. 详细了解文档对象模型(DOM)
  7. springsecurity原理执行流程_3. Spark原理-执行流程解析
  8. 运行 jar 文件_如何运行JAR文件
  9. 深度学习之CNN反向传播
  10. 手把手教你微信公众号如何给指定用户发送消息提醒
  11. iOS 打开扬声器以及插入耳机的操作
  12. Android Gradle学习(五) Extension详解
  13. Vue中显示echarts北京公交路线
  14. 常见的的水生植物图像
  15. 会编程的孩子有多厉害?8岁女儿写代码哄程序员爸爸开心,网友直呼:破防了!...
  16. 中年程序员失业的3条退路!
  17. C#字符串操作,转自韩迎龙博客
  18. 世界地图并不是世界的真实样貌!甚至误差非常大
  19. windows学习记录之MFC通过URL上传下载文件
  20. python保留小数点后位数_Python保留指定位数的小数

热门文章

  1. 计算机vb基础知识,计算机VB基础知识---知识导学.doc
  2. sqlyog恢复查询记录
  3. Redis命令:scan实现模糊查询
  4. RoundProgressBar(圆形进度条)
  5. 判断单链表是否有环及环的链接点(转)
  6. 自发光材质、panner、sin——移动的光栅
  7. pandas计算店家的每日营业额示例
  8. PEST分析顺丰服务需求_快递行业宏观环境分析
  9. 在单端输入应用中连接差分放大器
  10. 用于app的支付成功与失败页面