代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象的时候,客户端并不关心是否可以准确的得到这个对象,他只要一个能够提供该功能的对象而已,此时我们就可以返回该对象的代理。总而言之,客户端代码不能或者不想直接访问被调用对象,服务器这段额外的建立一个代理对象返回给客户端使用,那么这种设计方式就是代理模式。



自从JDK的版本到1.3以后,java语言通过java.lang.reflect库中,提供了三个类来直接支持代理模式。分别是:Proxy,InvocoationHandler和Method。Proxy类使得设计师能够在运行时间创建代理对象,当系统有了一个代理对象后,对源对象的方法调用会首先被分派给一个调用处理器(InvocationHandler)//接口,InvocationHandler接口中有一个invoke()方法,程序可以在调用处理器的invoke方法中截获这个调用,进行额外的操作。

创建动态代理对象的步骤:

1.指明一系列的接口来创建一个代理对象

2.创建一个调用处理器(InvocationHandler)对象

3.将这个代理指定为某个其他对象的代理对象

4.在调用处理器的invoke方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作。

其中代理模式在hibernate和spring中都有应用,下面代码模拟hibernate中的懒加载。

代码如下:

  1. <strong><span style="font-size:14px;">//代理和实际对象都要实现的接口
  2. interface Image{
  3. //随便定义一个方法
  4. public void show();
  5. }
  6.  
  7. //模拟客户端使用的代理
  8. class ImageProxy implements Image{
  9.  
  10. private Image image;
  11.  
  12. public ImageProxy(Image image) {
  13. super();
  14. this.image = image;
  15. }
  16.  
  17. @Override
  18. public void show() {
  19. //加入自己的代码逻辑 在用到这个show方法的时候 才会去真正的创建那个实实在在的对象
  20. if(null == image){
  21. image = new BigImage();
  22. }
  23. image.show();
  24. }
  25.  
  26. }
  27.  
  28. //实际的对象
  29. public class BigImage implements Image{
  30.  
  31. public BigImage(){
  32. try {
  33. Thread.sleep(5000);
  34. System.out.println("BigImage...");
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39.  
  40. @Override
  41. public void show() {
  42. System.out.println("梦似烟花心似水,同学少年不言情。。。");
  43. }
  44.  
  45. public static void main(String[] args) {
  46. //直接使用真正的对象 在new那个对象的时候会有的5000秒的延迟
  47. long stateTime1 = System.currentTimeMillis();
  48. Image image1 = new BigImage();
  49. System.out.println(System.currentTimeMillis() - stateTime1+"\n");
  50.  
  51. //使用代理,直接很快的创建了一个代理对象,在真正使用到对象的show方法的时候 才会有5000秒的延迟
  52. long stateTime = System.currentTimeMillis();
  53. Image image = new ImageProxy(null);
  54. System.out.println(System.currentTimeMillis() - stateTime);
  55. image.show();
  56.  
  57. }
  58.  
  59. }
  60.  
  61. </span></strong>





在spring中也使用了代理模式,其中spring的AOP就是代理模式的一个典型应用。

  1. <strong><span style="font-size:14px;">import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4.  
  5. //java动态代理 代理对象和被代理对象都要实现的接口
  6. interface Dog{
  7. public void info();
  8.  
  9. public void run();
  10. }
  11.  
  12. //模拟事务管理器
  13. class TxUtil{
  14.  
  15. public void beginTx(){
  16. System.out.println("...模拟事务开始...");
  17. }
  18.  
  19. public void endTx(){
  20. System.out.println("...模拟事务结束...\n");
  21. }
  22. }
  23.  
  24. //java动态代理的关键之一,InvocationHandler的实现类,这个类的invoke方法将成为最后代理对象方法的实现
  25. class LinkinInvocationHandler implements InvocationHandler{
  26. //需要被代理的对象
  27. private Object target;
  28.  
  29. public void setTarget(Object target) {
  30. this.target = target;
  31. }
  32.  
  33. @Override
  34. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  35. TxUtil txUtil = new TxUtil();
  36. txUtil.beginTx();
  37. //方法的反射 需要被代理的对象作为主调来调用方法
  38. Object result = method.invoke(target, args);
  39. txUtil.endTx();
  40. return result;
  41. }
  42.  
  43. }
  44.  
  45. //模拟一个获得代理对象的工厂
  46. class LinkinProxyFactory{
  47. public static Object getProxyInstance(Object target){
  48. LinkinInvocationHandler hander = new LinkinInvocationHandler();
  49. hander.setTarget(target);
  50. //改天复习下反射 注意下面方法的返回值
  51. return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), hander);
  52. }
  53. }
  54.  
  55. //被代理对象
  56. public class MyDog implements Dog{
  57.  
  58. @Override
  59. public void info() {
  60. System.out.println("忠犬8公...");
  61. }
  62.  
  63. @Override
  64. public void run() {
  65. System.out.println("很忠诚的...");
  66. }
  67.  
  68. public static void main(String[] args) {
  69. //获得一个被代理对象
  70. MyDog myDog = new MyDog();
  71. //以被代理对象作为参数获得一个代理对象 一般情况下编译类型都是接口
  72. Dog myDogProxy = (Dog) LinkinProxyFactory.getProxyInstance(myDog);
  73. myDogProxy.info();
  74. myDogProxy.run();
  75. }
  76.  
  77. }</span></strong>

linkin大话设计模式--代理模式的更多相关文章

  1. linkin大话设计模式--常用模式总结

    linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...

  2. linkin大话设计模式--建造模式

    linkin大话设计模式--建造模式 建造模式是对象的创建模式,可以讲一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象. 建造模式的结构: 抽象建造者 ...

  3. linkin大话设计模式--模板方法模式

    linkin大话设计模式--模板方法模式 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不 ...

  4. linkin大话设计模式--桥接模式

    linkin大话设计模式--桥接模式 桥接模式是一种结构化模式,他主要应对的是:由于实际的需要,某个类具有2个或者2个以上维度的变化,如果只是使用继承将无法实现功能,或者会使得设计变得相当的臃肿.我们 ...

  5. linkin大话设计模式--门面模式

    linkin大话设计模式--门面模式 随着系统的不断改进和开发,他们会变得越来越复杂,系统会生成大量的类,这使得程序的流程更加难以理解.门面模式可以为这些类提供一个简易的接口,从而简化访问这些类的复杂 ...

  6. linkin大话设计模式--策略模式

    linkin大话设计模式--策略模式 Strategy [ˈstrætədʒi]  策略 策略模式用于封装系列的算法,这些算法通常被封装在一个称为Context的类中,客户端程序可以自由的选择任何一种 ...

  7. linkin大话设计模式--命令模式

    linkin大话设计模式--命令模式 首先考虑一种应用情况,某个方法需要完成某一个功能,这个功能的大部分功能已经确定了,但是有可能少量的步骤没法确定,必须等到执行这个方法才可以确定. 也就是说,我们写 ...

  8. 大话设计模式--代理模式 proxy

    1. 代理模式: 为其他对象提供一种代理以控制这个对象的访问. 代理模式使用场合: a. 远程代理, 为一个对象在不同的地址空间提供局部代理,隐藏一个对象存在于不同地址空间的事实.如.net中WebS ...

  9. linkin大话设计模式--单例模式

    linkin大话设计模式 开文前先弱弱的问一句:什么是设计模式?我在研究java2ee的时候有研究过,在学js的时候也有看到.设计模式的概念最早源于建筑设计大师<建筑的永恒算法>一书,它表 ...

随机推荐

  1. python并开发编程之协程

    一 引出协成 并发的本质是:切换+保存状态 CPU在运行行一个任务时,会在两种情况下切走去执行其他任务,一是该任务发生了阻塞,二是运行该任务的时间过长 yeild可以保存状态,yeild状态保存与操作 ...

  2. 表单验证控件Verify.js

    自己工作常用到表单录入验证,就顺手写了一个验证控件,刚开始写得很烂.多年后翻出来,又优化了一下,增加了一些功能.拿出来分享分享. 主要功能就是表单的录入验证. * 1.当录入框必填时,在控件后生成红色 ...

  3. 日期插件-flatpickr

    github的仓库地址:https://github.com/chmln/flatpickr 手册地址:http://www.htmleaf.com/Demo/201608213895.html    ...

  4. 名片管理系统v1.1(main)

    # version: 1.1# author: Mark import cords_tools while True: # 显示界面    cords_tools.show_cords() cords ...

  5. 【机器学习学习】SKlearn + XGBoost 预测 Titanic 乘客幸存

    Titanic 数据集是从 kaggle下载的,下载地址:https://www.kaggle.com/c/titanic/data 数据一共又3个文件,分别是:train.csv,test.csv, ...

  6. b9934107349625014ec251e1333d73a8 这个代码是mad5值

    Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321(R.Rives ...

  7. deeplearning.ai 神经网络和深度学习 week3 浅层神经网络 听课笔记

    1. 第i层网络 Z[i] = W[i]A[i-1] + B[i],A[i] = f[i](Z[i]). 其中, W[i]形状是n[i]*n[i-1],n[i]是第i层神经元的数量: A[i-1]是第 ...

  8. JavaScript中数组map()方法

    JavaScript 数组map()方法创建一个新的数组使用调用此数组中的每个元素上所提供的函数的结果.语法 ? 1 array.map(callback[, thisObject]); 下面是参数的 ...

  9. CommonJS,AMD,RequireJS的区别

    RequireJS实现了AMD的API. CommonJS是使用exports对象来定义模块的一种方法,它定义了模块的内容.简单地实现一个CommonJS的定义就像下面这样: // someModul ...

  10. bzoj:1230: [Usaco2008 Nov]lites 开关灯

    Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每 ...