zoukankan      html  css  js  c++  java
  • 代理模式学习

    说到代理我能想到的是代理商,例如IBM需要卖本本,一般不会自己去卖,而是把货

    给代理商,委托他们来卖,用户如果需要买ibm的本本,就可以通过这些代理商买到。

    用官方的一句话说,代理模式通过使用代理来替代实际的对象,使程序能够控制对该对象的访问。

    其实这些用类图来表示就是很简单的一个关系,代理模式并不是一个很复杂的模式,只是使用最简单的抽象类或者接口来封装一个实现的过程。


    其实最重要的是代理对象中包含了真实对象的引用,这样代理对象就可以再执行真实对象的方法前进行一些操作,就像打日志,校验权限等,而且有不用破坏真实对象原有的逻辑,这样符合开-闭原则(Open-Closed principle,简称OCP

    静态代理

    代理模式在代码中的实现分静态代理和动态代理。静态代理则是基于上述原理我们自己的实现。

    我们简单的实现一个类,接口就不贴了。

    代码
     1 package proxy;
     2 
     3 public class HelloWorldImpl implements HelloWorld {
     4 
     5     public void print() {
     6         System.out.println("helloworld");
     7 
     8     }
     9     
    10     public void say() {
    11         System.out.println("Say Hello!");
    12     }   
    13 
    14 }

     作为静态代理来说,之需要简单的扩充一下实现类,把实现类作为一个属性传入代理即可。

    代码
     1 package proxy;
     2 
     3 public class StaticProxyInstance {
     4     
     5     private HelloWorld helloWorld;
     6     
     7     /**
     8      * proxy {@link HelloWorld#print()} method
     9      */
    10     public void invoke() {
    11         helloWorld.print();
    12     }
    13 
    14     public HelloWorld getHelloWorld() {
    15         return helloWorld;
    16     }
    17 
    18     public void setHelloWorld(HelloWorld helloWorld) {
    19         this.helloWorld = helloWorld;
    20     }
    21     
    22 }

    这样总的来说比较灵活。这个依赖关系是我们自己做的,我们完全可以交给spring处理。按照上面的这种做法有一个缺点,如果接口中方法很多,那么我们实现每一个方法都要添加一个方法,影响了我们的业务处理。 

    Java实现的动态代理

    Java中的动态代理需要实现InvocationHandler接口。同时,需要一个被代理的对象,当访问这个代理对象的时候,InvocationHandler接口的invoke方法将被触发。最出名的动态代理的例子就是springAOP,可以在方法前等地方打印日志,操纵数据等。

    Java的动态代理必须要提供一个返回代理对象的地方。Invoke方法只是用来执行。

    代码
     1 package proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Proxy;
     6 
     7 public class DynamicProxyInstance implements InvocationHandler {
     8     
     9     private Object object;
    10     
    11     public Object invoke(Object proxy, Method method, Object[] args)
    12             throws Throwable {
    13         //在方法调用前输出
    14         System.out.println("Welcome");          
    15         Object result = method.invoke(object, args);
    16         System.out.println("after the method invoke");
    17         return result; 
    18     }
    19 
    20     public Object bindRelation(Object object) {
    21         this.object = object;
    22         return Proxy.newProxyInstance(object.getClass().getClassLoader(),
    23                 object.getClass().getInterfaces(), this);
    24     }
    25 }

    code中的那样,简单的使用一个bindRelation方法来返回代理对象,最重要的代码为:

    1 Proxy.newProxyInstance(object.getClass().getClassLoader(),
    2                 object.getClass().getInterfaces(), this);

    通过Proxy类新建了一个代理实例。

    代码
    1 HelloWorld helloWorld = new HelloWorldImpl();          
    2 DynamicProxyInstance dp = new DynamicProxyInstance();       
    3 HelloWorld helloWorld1 = (HelloWorld)dp.bindRelation(helloWorld);           
    4 helloWorld1.print();

    只有通过这个代理实例执行的方法才会被代理接口绑定做一些其他处理。 

  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/xiziyin/p/1617249.html
Copyright © 2011-2022 走看看