• 代理模式


    代理模式

     给某一个对象提供一个代理对象,并由代理对象控制原对象的引用。

     有些时候,一个客户不想或者不能直接引用一个对象,可以通过代理对象在客户端和目标对象之前起到中介作用。代理模式的角色:

    1.抽象对象角色

    声明了目标对象和代理对象共同的接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。

    2.目标对象角色

    定义了代理对象所代表的目标对象

    3.代理对象角色

    代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象,代理对象提供一个目标对象相同的接口,以便可以在任何时候替代目标对象。

    静态代理实例

    假如一个接口里面有一个方法,想在调用这个接口的前后加东西,就可以使用代理模式。静态代理是代理模式最简单的实现,定义一个静态代理接口

    1 public interface StaticHelloWorld {
    2     void print();
    3

    实现类

    1 public class StaticHelloWorldImpl implements StaticHelloWorld{
    2 
    3     @Override
    4     public void print() {
    5         System.out.println("hello world");
    6     }
    7 
    8

    代理对象,重点在于代理对象和实际对象实现的是同一个接口,希望在任何时候让代理对象替代实际对象

     1 public class StaticProxy implements StaticHelloWorld{
     2     
     3     private StaticHelloWorldImpl staticHelloWorldImpl;
     4     
     5     public StaticProxy(){
     6         if(staticHelloWorldImpl == null){
     7             staticHelloWorldImpl = new StaticHelloWorldImpl();
     8         }
     9     }
    10     
    11     public void print() {
    12         System.out.println("before HelloWorld");
    13         staticHelloWorldImpl.print();
    14         System.out.println("after HelloWorld");
    15     }
    16 
    17 }

    main

    1 public static void main(String[] args) {
    2         StaticProxy proxy = new StaticProxy();
    3         proxy.print();
    4     }

    结果是

    1 before HelloWorld
    2 hello world
    3 after HelloWorld

    静态代理的缺点

    静态代理的特点是静态代理的代理类是程序员创建的,程序运行前静态代理的.class文件已经存在了。这种模式在代理量比较小时还可以,但是代理量大了就有很大的缺点:

    1.代理内容无法复用,如果想换一种代理内容,比如在helloworld前后不想输入before和after..,想输出别的东西,那么就必须重新写一个代理对象。这样容易造成代理对象的膨胀。

    2.接口里面新增了一个方法,实际对象实现了这个方法,代理对象也必须新增内容,去给这个新增方法增加代理内容。

    动态代理实例

    动态代理接口

    1 public interface DynamicHelloWorld {
    2     String print();
    3 }

    动态代理接口的实现

    1 public class DynamicHelloWorldImpl implements DynamicHelloWorld{
    2 
    3     public String print() {
    4         System.out.println("hello world");
    5         return "DynamicHelloWorldImpl";
    6     }
    7 
    8 }

    动态代理类,在java中动态代理需要实现InvocationHandler接口。该接口只有一个invoke方法。

    第一种

     1 public class DynamicProxy implements InvocationHandler
     2 {
     3     private Object target;
     4     
     5     public Object newInstance(Object target)
     6     {
     7         this.target = target;
     8         
     9         return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
    10                 target.getClass().getInterfaces(), this);
    11     }
    12     
    13     public Object invoke(Object proxy, Method method, Object[] args)
    14             throws Throwable
    15     {
    16         System.out.println("Before DynamicProxy");
    17         method.invoke(target, args);
    18         System.out.println("After DynamicProxy");
    19         return null;
    20     }
    21 }

    第二种 

     1 public class DynamicProxy implements InvocationHandler
     2 {
     3     private Object target;
     4     
     5     public DynamicProxy(Object target)
     6     {
     7         this.target = target;
     8     }
     9     
    10     public Object invoke(Object proxy, Method method, Object[] args)
    11             throws Throwable
    12     {
    13         System.out.println("Before DynamicProxy");
    14         method.invoke(target, args);
    15         System.out.println("After DynamicProxy");
    16         return null;
    17     }
    18 }

    第一种main函数

     1 public class DynamicTestMain
     2 {
     3     public static void main(String[] args) throws Exception
     4     {
     5         DynamicProxy dp = new DynamicProxy();
     6         DynamicHelloWorld dhwi = new DynamicHelloWorldImpl();
     7         DynamicHelloWorld dhw = (DynamicHelloWorld)dp.newInstance(dhwi);
     8         dhw.print();
     9     }
    10 }

    第二种main函数

     1 public class DynamicTestMain
     2 {
     3     public static void main(String[] args) throws Exception
     4     {
     5         DynamicHelloWorld dhwi = new DynamicHelloWorldImpl();
     6         InvocationHandler ih = new DynamicProxy(dhwi);
     7         DynamicHelloWorld dhw = 
     8                 (DynamicHelloWorld)Proxy.
     9                 newProxyInstance(DynamicHelloWorld.class.getClassLoader(), 
    10                                  new Class<?>[]{DynamicHelloWorld.class}, ih);
    11         dhw.print();
    12     }
    13 }

    不管哪种写法,运行结果都是一样的:

    Before DynamicProxy
    Enter DynamicHelloWorldImpl.print()
    After DynamicProxy

     动态代理,利用动态编译+反射技术,把实际对象的方法调用转换成对传入的InvocationHandler接口实现类的invoke方法的调用。

    动态代理的优缺点

    优点:

    1.类少了

    2.代理内容的实现类可以复用,可以给A接口用,也可以给B接口用。

    缺点:

    只能针对于接口生成代理,不能针对一个类生成代理。如果想要为某一个单独的类实现一个代理可以考虑GGLIB技术。

  • 相关阅读:
    引用类型中的push()、pop()、shift()方法
    SQL Server ->>监控和管理Tempdb
    SQL Server ->> 与SQL Server服务配置相关的DMV
    SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表)
    SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Row-Level Security(行级别安全控制)
    SQL Server ->> SQL Server 2016新特性之 -- sp_set_session_context存储过程和SESSION_CONTEXT函数
    SQL Server ->> Enable Instant File Initialization(开启文件及时初始化)
    SQL Server ->> 尝试优化ETL中优化Merge性能
    SQL Server ->> 校检函数CHECKSUM、CHECKSUM_AGG、BINARY_CHECKSUM和HASHBYTES
    SQL Server ->> Database Promgramming Object Security Control(数据库编程对象安全控制)
  • 原文地址:https://www.cnblogs.com/tp123/p/6497139.html
Copyright © 2020-2023  润新知