代理设计模式浅析

2021-07-26  本文已影响0人  碧云天EthanLee
概述

代理设计模式的应用可以说是非常之广泛。比如说 Retrofit封装OkHttp,就是用的动态代理的方式,生成了代理接口的对象(create 方法),从而代理 OkHttp生成网络请求的 Call对象。看代理模式定义:为其他对象提供一种代理以控制对这个对象的访问。结合现实生活来描述,就比如说客户取银行柜台办卡,那么客户就是被代理者,银行柜员则代理客户办卡。代理模式分为静态代理和动态代理,在日常开发过程中我们可能见到动态代理多一点。下面看一下。

一、静态代理

下面就拿柜员帮客户办卡来看看静态代理。先创建一个抽象业务:

public interface IProxy {
    void play(); // 办卡
}

下面创建办卡客户类型,继承 IProxy :

/**
 * 办卡客户
 */

public class Customer implements IProxy{
    private static final String TAG = "TAG_Customer";
    @Override
    public void play() {
        Log.d(TAG, "帮我办卡就好");
    }
}

客户 play() 方法里执行办卡操作,再来一个银行柜员,也是继承自 IProxy:

/**
 * 银行柜员
 */
public class Banker implements IProxy{
    private static final String TAG = "TAG_Banker";
    // 持有客户(被代理者)对象
    private IProxy mCustomer;

    public Banker(IProxy customer){
        this.mCustomer = customer;
    }
    @Override
    public void play() {
        Log.d(TAG, "我来帮您办卡,需要办会员吗?");
        this.mCustomer.play(); // 办卡
        Log.d(TAG,"您好,卡给您办完了");
    }
}

上面可以看到,银行柜员将持有客户的对象(mCustomer),调用了客户办卡的play()方法,这就是代理。与此同时上面 Log我们可以看到,银行柜员帮客户办卡的同时还可以做些别的事,比如说推销办会员啊、推销理财产品啊啥的。下面看调用:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Banker banker = new Banker(new Customer()); // 创建代理者
        banker.play(); // 代理者开始操作
    }
}
// Log
D/TAG_Banker: 我来帮您办卡,需要办会员吗?
D/TAG_Customer: 帮我办卡就好
D/TAG_Banker: 您好,卡给您办完了
二、动态代理

开头说了,动态代理在日常开发中应用还是很广泛的。就比如大名鼎鼎的 Retrofit的核心实现就是靠动态代理。

动态代理是通过反射来生成被代理类对象的,所以在源码阶段不需要知道被代理者的类型。这样的好处就是解耦。java提供了一个便捷的动态代理接口 InvocationHandler,被代理者的方法就是在该接口实现类的 invoke方法里被调用。下面写一个 InvocationHandler实现类:

public class ProxyHandler implements InvocationHandler {
    private static final String TAG = "ProxyBanker";
    private Object mCustomer;
    public ProxyHandler(Class<?> customer){
        try {
            // 反射生成对象
            mCustomer = customer.newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 反射调用被代理者对象
        Object object = method.invoke(mCustomer, args);
        return object;
    }
}

可以看到上面构造方法参数类型是被代理者的 Class类型,所以这里不需要提前知道被代理者是啥类型,因为被代理者对象通过反射生成,这里这样做也是为了解耦。然后被代理者的方法也是被动态调用。下面来看一下使用:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 动态传入类型
        IProxy proxy = initProxy(Customer.class);
        // 调用
        proxy.play();
    }
    private <T extends Object> T initProxy(Class<T> clz){
        // ProxyHandler 的参数类型是 Class,无论是什么样的被代理者都可以
        ProxyHandler handler = new ProxyHandler(clz);
        // 获取被代理者实现的的接口
        Class interfaceClass = clz.getInterfaces()[0];
        // 动态构建一个
        T pBanker = (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                new Class[]{interfaceClass},handler);
        return pBanker;
    }
}

我们可以看到上面,initProxy()方法,我们只需要把被代理者的类型(Customer.class)作为参数传入,即可动态生成代理者对象,然后调用相关方法。initProxy()方法相当于是一个简单的封装,只要我们封装好了就可以给外界使用,并且完全解耦。

上一篇 下一篇

猜你喜欢

热点阅读