设计模式学习笔记(12)--代理设计模式

1.定义

       代理模式(Proxy Pattern) :给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。

2.uml图

3.代码

上图简单代码实现(静态代理):

package com.wuhuiskiff.www.proxy.code.simple;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:31
 * @Description:抽象的角色
 */
public interface Subject {
    // 客户端的请求
     void request();
}
package com.wuhuiskiff.www.proxy.code.simple;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:32
 * @Description:
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实角色干的事。。。");
    }
}
package com.wuhuiskiff.www.proxy.code.simple;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:33
 * @Description:
 */
public class ProxySubject implements Subject {

    private RealSubject realSubject;
    public ProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        this.preRequest();
        this.realSubject.request();
        this.postRequest();
    }

    private void preRequest(){
        System.out.println("在请求之前,业务处理。。。");
    }

    private void postRequest(){
        System.out.println("在请求之后,业务处理。。。");
    }
}
package com.wuhuiskiff.www.proxy.code.simple;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:37
 * @Description:
 */
public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject subject = new ProxySubject(realSubject);
        subject.request();
    }
}

(2).动态代理:

package com.wuhuiskiff.www.proxy.code.invoke;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:55
 * @Description:
 */
public interface Subject {
    void request();
}
package com.wuhuiskiff.www.proxy.code.invoke;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 21:56
 * @Description:
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实角色所能做的事。。。");
    }
}
package com.wuhuiskiff.www.proxy.code.invoke;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 22:03
 * @Description:
 */
public class DynamicSubject implements InvocationHandler {
    private Object sub;

    // 通过构造方法传入一个对象
    public DynamicSubject(Object sub) {
        this.sub = sub;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("before method");
        // 其实调用的是被代理对象中的方法,例如这个是调用的是realSubject中的request方法
        method.invoke(this.sub, args);
        System.out.println("after method");
        return null;
    }
}
package com.wuhuiskiff.www.proxy.code.invoke;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 22:06
 * @Description:
 * 所谓Dynamic Proxy是这样的一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给他
 * ,然后改class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用。
 * 当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,
 * 由它接管实际的工作
 */
public class Client {
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        InvocationHandler handler = new DynamicSubject(subject);
        Class<? extends InvocationHandler> classType = handler.getClass();
        // 生成一个代理对象,第二参数是RealSubject实现的接口
       Subject subject1 = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), subject.getClass().getInterfaces(),
                handler);

       subject1.request();
//       class com.sun.proxy.$Proxy0
        System.out.println(subject1.getClass());
    }
}

(3)Vector的代理类:

package com.wuhuiskiff.www.proxy.code.vector;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Vector;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/17 23:40
 * @Description:
 */
public class VectorProxy implements InvocationHandler {
    private Object object;

    public VectorProxy(Object object) {
        this.object = object;
    }

    public static Object factory(Object object){
        Class<?> classType = object.getClass();
        // 生成代理的实例
        VectorProxy vectorProxy = new VectorProxy(object);
        return Proxy.newProxyInstance(classType.getClassLoader(),classType.getInterfaces(),vectorProxy);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method invoke");
        if(null != args){
            for (Object arg:args) {
                System.out.println("参数:" + arg);
            }
        }
       Object result =  method.invoke(this.object,args);
        System.out.println("after method invoke");
        return result;
    }

    public static void main(String[] args) {
        List list = (List) factory(new Vector());
        System.out.println(list.getClass());
        // 代理类调用method.invoke方法
        list.add("张山");
        list.add("skiff");
        System.out.println("---------------------");
        list.remove(0);
    }

}

4.优缺点

代理模式的优点

  • 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
  • 远程代理使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
  • 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
  • 保护代理可以控制对真实对象的使用权限。

代理模式的缺点

  • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  • 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

5.应用

  1.  Java RMI (Remote Method Invocation,远程方法调用)。
  2.  EJB、Web Service等分布式技术都是代理模式的应用。在EJB中使用了RMI机制,远程服务器中的企业级Bean在本地有一个桩代理,客户端通过桩来调用远程对象中定义的方法,而无须直接与远程对象交互。在EJB的使用中需要提供一个公共的接口,客户端针对该接口进行编程,无须知道桩以及远程EJB的实现细节。
  3.  Spring 框架中的AOP技术也是代理模式的应用,在Spring AOP中应用了动态代理(Dynamic Proxy)技术。

6.总结

代理模式包含三个角色:

  • 抽象主题角色声明了真实主题和代理主题的共同接口;
  • 代理主题角色内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象;
  • 真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。

猜你喜欢

转载自blog.csdn.net/u011662320/article/details/87611546