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

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11401233.html

    1. 定义
    为其他对象提供一种代理以控制这个对象的访问。

    2. 结构图

    Proxy:代理对象。通常具有如下功能。

    • 实现与具体的目标对象一样的接口,这样就可以使用代理来代替具体的目标对象。
    • 保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象。
    • 可以控制对具体目标对象的访问,并可以负责创建和删除它。

    Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象。
    RealSubject:具体的目标对象,真正实现目标接口要求的功能。

     

    3. 本质
    代理模式的本质:控制对象访问。 

    4. Code Demo

    Subject.java

    1 package org.fool.dp.proxy;
    2 
    3 public interface Subject {
    4     void request();
    5 }

    RealSubject.java

    1 package org.fool.dp.proxy;
    2 
    3 public class RealSubject implements Subject {
    4     @Override
    5     public void request() {
    6         System.out.println("real subject invoked...");
    7     }
    8 }

    ProxySubject.java

     1 package org.fool.dp.proxy;
     2 
     3 public class ProxySubject implements Subject {
     4     private RealSubject realSubject;
     5 
     6     @Override
     7     public void request() {
     8         System.out.println("proxy start...");
     9 
    10         if (null == realSubject) {
    11             realSubject = new RealSubject();
    12         }
    13 
    14         realSubject.request();
    15 
    16         System.out.println("proxy end...");
    17     }
    18 }

    Client.java

    1 package org.fool.dp.proxy;
    2 
    3 public class Client {
    4     public static void main(String[] args) {
    5         Subject proxySubject = new ProxySubject();
    6         proxySubject.request();
    7     }
    8 }

    5. 动态代理

    Java对代理模式提供了内建的支持,在java.lang.reflect包下面,提供了一个Proxy的类和一个InvocationHandler的接口。
    通常把前面自己实现的代理模式称为Java的静态代理。这种实现方式有一个较大的缺点,就是如果Subject接口发生变化,那么代理类和具体的目标实现都要变化,不是很灵活。而使用Java内建的对代理模式支持的功能来实现则没有这个问题。
    通常把使用Java内建的对代理模式支持的功能来实现的代理称为Java的动态代理。动态代理跟静态代理相比,明显的变化是:静态代理实现的时候,在Subject接口上定义很多的方法,代理类里面自然也要实现很多方法;而动态代理实现的时候,虽然Subject接口上定义了很多方法,但是动态代理类始终只有一个invoke方法。这样,当Subject接口发生变化的时候,动态代理的接口就不需要跟着变化了。
    Java的动态代理目前只能代理接口,基本的实现是依靠Java的反射机制和动态生成class的技术,来动态生成被代理的接口的实现对象。
    代理模式在客户和被客户访问的对象之间,引入了一定程度的间接性,客户是直接使用代理,让代理来与被访问的对象进行交互。不同的代理类型,这种附加的间接性有不同的用途,也就具有不同的特点。

    动态代理Demo

    Subject.java

    1 package org.fool.dp.dynamicproxy;
    2 
    3 public interface Subject {
    4     void request();
    5 }

    RealSubject.java

    1 package org.fool.dp.dynamicproxy;
    2 
    3 public class RealSubject implements Subject {
    4     @Override
    5     public void request() {
    6         System.out.println("real subject invoked...");
    7     }
    8 }

    DynamicSubject.java

     1 package org.fool.dp.dynamicproxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class DynamicSubject implements InvocationHandler {
     7     private Object subject;
     8 
     9     public DynamicSubject(Object subject) {
    10         this.subject = subject;
    11     }
    12 
    13     @Override
    14     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    15         System.out.println("before calling: " + method);
    16 
    17         method.invoke(subject, args);
    18 
    19         System.out.println("after calling: " + method);
    20 
    21         return null;
    22     }
    23 }

    Client.java

     1 package org.fool.dp.dynamicproxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Proxy;
     5 
     6 public class Client {
     7     public static void main(String[] args) {
     8         Subject realSubject = new RealSubject();
     9 
    10         InvocationHandler handler = new DynamicSubject(realSubject);
    11 
    12         Class<? extends InvocationHandler> handlerClass = handler.getClass();
    13 
    14         Subject proxySubject = (Subject) Proxy.newProxyInstance(handlerClass.getClassLoader(),
    15                 realSubject.getClass().getInterfaces(), handler);
    16 
    17         proxySubject.request();
    18     }
    19 }
  • 相关阅读:
    Centos安装mysql 5.6
    Cache和Buffer都是缓存,主要的区别是什么?
    服务器遭受攻击后的处理过程
    划船学python——语法(二)循环语句
    划船学python——语法(一)条件语句
    划船学python——初识数据类型
    FTP与SFTP区别
    说一说Nginx Proxy配置
    Virtual Box 中的虚拟系统无法调整分辨率(无法自适应窗口大小)
    [error]subprocess.CalledProcessError: Command '['which', 'g++']' returned non-zero exit status 1.
  • 原文地址:https://www.cnblogs.com/agilestyle/p/11401233.html
Copyright © 2011-2022 走看看