设计模式 -- 代理模式

概述

为其他对象 提供一种代理,以控制对这个对象的访问,代理大概分为两类,静态代理和动态代理

UML 类图

这里写图片描述

静态代理##

Subject
Subject 定义了RealSubject 和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy

public interface Subject {

    void request();
}

RealSubject
RealSubject 代表了Proxy所代理的真实实体

public class RealSubjiect implements Subject {
    @Override
    public void request() {
        Log.d("mmm","调用了真实对象");
    }
}

Proxy
Proxy类,保存一个真实对象的引用,使得代理可以访问实体,并实现Sunject接口,这样代理就可以代替实体

public class ProxySubject implements Subject {

    private RealSubjiect mRealSubject;

    public ProxySubject() {
        if (mRealSubject == null) {
            mRealSubject = new RealSubjiect();
        }
    }

    @Override
    public void request() {
        //  to do something
        mRealSubject.request();
        //  to do something
    }
}

客户端调用

		//静态代理
        ProxySubject proxySubject = new ProxySubject();
        proxySubject.request();

动态代理

静态代理在编译期间,代理类就已经被我们写了出来,这样每一个RealSubject类都对应一个代理类,编写特别麻烦,动态代理,我们不用手动编写代理类,只要简单的指定一组接口,及委托类(真实类)对象,便能动态的获取代理类、

要实现动态代理需要借助java中的俩个接口或类,InvocationHandler(接口)和Proxy(类),简单介绍一下

InvocationHandler 接口
每个动态代理类都必须要实现InvocationHandler 这个接口,并且每一个代理类的实例都关联到了一个handler,当我们通过一个代理对象调用一个方法的时候,这个方法的调用就会被转发到InvocationHandler 这个接口的invoke方法进行调用,我么来看一下InvocationHandler 这个接口的 唯一方法invoke

invoke

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

这个方法接收三个参数,和一个返回值,意思分别为下:

proxy:指代理的对象
method:指的是我们所要调用的真实对象的方法的Method 对象
args: 指的调用方法的参数
返回的object 是指真实方法的返回值

Proxy 类
Proxy类的作用,就是用来动态的创建代理对象,我们经常使用的是newProxyInstance这个方法

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException

参数理解
loader:一个ClassLoader对象,定义了由哪一个ClassLoader对象,对生成的代理类进行加载
interfaces:一个interface对象的数组,表示我将要给代理类提供一组什么样的接口
hInvocationHandler 对象,表示我动态代理对象在调用的方法的时候,会关联那个InvocationHandler 对象上
返回值,返回一个代理类

实例

public interface Subject {

    void request();
}

public class RealSubjiect implements Subject {
    @Override
    public void request() {
        Log.d("mmm","调用了真实对象");
    }
}
public class ProxyHandler implements InvocationHandler {

    private RealSubjiect mRealSubject;

    public ProxyHandler() {
        if (mRealSubject == null) {
            mRealSubject = new RealSubjiect();
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //before
        Object result = method.invoke(mRealSubject, args);
        //after
        return result;
    }
}
  //动态代理

        //创建调用处理器对象
        ProxyHandler proxyHandler = new ProxyHandler();
        //动态生成代理对象
        Subject proxy = (Subject) Proxy.newProxyInstance(RealSubjiect.class.getClassLoader(), RealSubjiect.class.getInterfaces(), proxyHandler);
        //调用方法
        proxy.request();

如何动态创建的代理类
newProxyInstance 他内部主要做了这几项工作,生成的代理类对象

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
{
    //1. 根据类加载器和接口创建代理类
    Class clazz = Proxy.getProxyClass(loader, interfaces); 
    //2. 获得代理类的带参数的构造函数
    Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
    //3. 创建代理对象,并制定调用处理器实例为参数传入
    Interface Proxy = (Interface)constructor.newInstance(new Object[] {handler});
}

代理类调用方法是如何转发到InvocationHandler的invoke方法的
动态生成的代理类,大概是这个样子的

public final class $Proxy1 extends Proxy implements Subject{
    private InvocationHandler h;
    private $Proxy1(){}
    public $Proxy1(InvocationHandler h){
        this.h = h;
    }
    public int request(int i){
        Method method = Subject.class.getMethod("request", new Class[]{int.class}); //创建method对象
        return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); //调用了invoke方法
    }
}

他有以下几个特点
1 继承了Proxy接口,实现了Proxy.newProxyInstance中提供接口数组
2 是public final的
3 命名方式为 $ProxyN,其中N会慢慢增加,一开始是 P r o x y 1 , 接 下 来 是 Proxy1,接下来是 Proxy1Proxy2…
4 有一个参数为 InvocationHandler 的构造函数。这个从 Proxy.newProxyInstance() 函数内部的clazz.getConstructor(new Class[] { InvocationHandler.class }) 可以看出。

我是怎么知道的?
参考https://www.cnblogs.com/gonjan-blog/p/6685611.html
https://www.cnblogs.com/huhx/p/dynamicTheoryAdvance.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值