设计模式_代理模式

Posted zhenghengbin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式_代理模式相关的知识,希望对你有一定的参考价值。

不知不觉今天已经7月底了,时间过得真快,这个月真热,这篇文章主要来介绍代理模式。

概述

代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问

如下图所示

技术分享图片

UML类图

技术分享图片

代理模式类别

技术分享图片

代码实现

这里是结合springAop,仿造它的实现

静态代理

public interface Subject {

    void request();
}


// 请求的真实目标对象
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("real subject execute request");
    }
}


// 代理对象
public class Proxy implements Subject {

    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("before");
        try {
            realSubject.request();
        } catch (Exception e) {
            System.out.println("ex:" + e);
            throw e;
        } finally {
            System.out.println("after");
        }


    }
}

客户端调用代码

public class Client {

    public static void main(String[] args) throws Exception {
        Subject subject = new Proxy(new RealSubject());

        subject.request();

    }
}

运行结果

before
real subject execute request
after

静态代理有一个很明显的缺点:代理的方法越多,重复代码越多。
就不符合DRY原则。于是 就产生了动态代理

动态代理

jdk代理

JDK 为我们提供了一种动态代理的实现,通过实现 InvocationHandler 接口来实现动态代理。

代理类代码

public class JdkProxySubject implements InvocationHandler {

    private RealSubject realSubject;

    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = null;
        try {
            result = method.invoke(realSubject, args);
        } catch (Exception e) {
            System.out.println("ex" + e);
            throw e;
        } finally {
            System.out.println("after");
        }


        return result;
    }
}

客户端类代码

public class Client {

    public static void main(String[] args) throws Exception {
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class
                .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));

        subject.request();

    }
}

运行结果

before
real subject execute request
after

上面讲了动态代理是解决代码重复的问题。我们来验证下

首先,在Subject 接口中增加一个hello方法

public interface Subject {

    void request();

    void hello();
}


public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("real subject execute request");
    }

    @Override
    public void hello() {
        System.out.println("real subject execute hello");
    }
}

静态代理类 如果想要代理hello 这个方法。就要在代理类中实现这个方法

public class Proxy implements Subject {

    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }


    @Override
    public void hello() {
        ...
    }
}

我们看动态代理类,无需改变,直接运行测试类

public class Client {

    public static void main(String[] args) throws Exception {
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class
                .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));

        subject.hello();

    }
}

运行结果

before
real subject execute hello
after
Cglib代理

代理类

public class DemoMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before in cglib");
        Object result = null;
        try {
            result = proxy.invokeSuper(object,args);
        }catch (Exception e){
            System.out.println("get ex :" + e.getMessage());
            throw e;
        }finally {
            System.out.println("after in cglib");
        }
        return result;
    }
}

调用

public class Client {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new DemoMethodInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.request();
    }
}

运行结果

before in cglib
real subject execute request
after in cglib

JDK代理和Cglib代理区别

  • JDK代理只能针对有接口的类的方法进行代理
  • Cglib基于继承来实现代理,无法对static、final 类进行代理
  • Cglib基于继承来实现代理,无法对private、static 方法 进行代理

代理模式暂时先分析到这,玩的开心!

以上是关于设计模式_代理模式的主要内容,如果未能解决你的问题,请参考以下文章

代理模式(静态代理动态代理)代码实战(详细)

是否有在单个活动中处理多个片段的 Android 设计模式?

设计模式_代理模式_动态代理

代理模式_静态代理

13.设计模式_代理模式

设计模式07_代理模式