代理设计模式(三) - 动态代理

前言

代理设计模式系列文章
代理设计模式(一) - 定义、角色划分
代理设计模式(二) - 静态代理
代理设计模式(三) - 动态代理
代理设计模式(四) - 实现 Retrofit 的 onCreate()

1. 动态代理?


动态代理是 Java 给我们提供了一套动态代理机制,那么接下来继续看如何用动态代理实现 银行工作人员帮我们办理业务;

2. 银行工作人员帮我们办理业务 - 动态代理实现


思路:
1>:首先创建目标接口IBank,里边写一个applyBank()办卡的方法,对于以后新增的方法直接在 IBank接口中添加即可;
2>:定义BankInvocationHandler,实现InvocationHandler接口,然后重写 invoke()方法;
3>:定义被代理对象Man,即就是我或者办卡的人,让其实现 IBank即可,重写所有方法;
4>:定义Client进行测试,对于以后新增的方法,可以直接 使用被代理对象 man来调用所有新增的方法即可;

2. 代码如下


1>:创建 IBank接口如下:
/**
 * Email: [email protected]
 * Created by Novate 2018/6/2 10:10
 * Version 1.0
 * Params:
 * Description:    银行办理业务 - 目标接口
*/

public interface IBank {

    /**
     * 申请办卡
     */
    void applyBank() ;

    /**
     * 挂失
     */
    void lostBank() ;

    /**
     * 额外的业务
     */
    void extraBank() ;
}
2>:定义 被代理对象Man,让其实现 IBank接口,并实现 applyBank()、lostBank()、extraBank(),这3个方法;
/**
 * Email: [email protected]
 * Created by Novate 2018/6/2 10:13
 * Version 1.0
 * Params:
 * Description:    被代理的对象 - 我(办卡的人)
 */

public class Man implements IBank {
    private String name;

    public Man(String name){
        this.name = name;
    }

    /**
     * 自己的一些操作
     */
    @Override
    public void applyBank() {
        System.out.println(name + " 申请办卡");
    }

    @Override
    public void lostBank() {
        System.out.println(name + " 申请挂失");
    }

    @Override
    public void extraBank() {
        System.out.println(name + " 额外业务");
    }
}
3>:定义动态代理 BankInvocationHandler,实现InvocationHandler接口,然后重写 invoke()方法:
/**
 * Email: [email protected]
 * Created by Novate 2018/6/2 10:36
 * Version 1.0
 * Params:
 * Description:    银行办理业务 - 动态代理 - InvocationHandler
*/

public class BankInvocationHandler implements InvocationHandler{


    // Object就是被代理的对象 Man
    private Object mObject ;
    public BankInvocationHandler(Object object){
        this.mObject = object ;
    }

    /**
     * 执行方法,目标接口调用的方法都会来到这里面
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        System.out.println(method.getName());
//      System.out.println(args.toString());

        System.out.println("开始受理");
        // 调用被代理对象的方法,这里其实调用的就是 man 里面的 applyBank()方法,最终调用的是jni
        Object voidObject = method.invoke(mObject, args);
        System.out.println("操作完毕");

        return voidObject;
    }
}
4>:定义Client进行测试,对于以后 IBank接口中新增的lostBank()、extraBank()方法,直接用 被代理对象man调用新增的lostBank()、extraBank()方法即可:
/**
 * Email: [email protected]
 * Created by Novate 2018/6/2 10:32
 * Version 1.0
 * Params:
 * Description:    动态代理测试代码
*/

public class Client {
    public static void main(String[] args){

        Man man = new Man("Novate") ;


        // 返回的是IBank的一个实例对象,而不在是一个接口,这个对象是由java给我们创建的
        IBank bank = (IBank) Proxy.newProxyInstance(
                IBank.class.getClassLoader() ,   // 类加载器 ClassLoader
                new Class[]{IBank.class},    // 目标接口IBank,这里必须是接口
                new BankInvocationHandler(man)    // InvocationHandler
        );


        // 当调用这个方法时候,会来到BankInvocationHandler的invoke()方法
        bank.applyBank();
        bank.lostBank();
        bank.extraBank();
    }
}
运行结果如下
开始受理
Novate 申请办卡
操作完毕
开始受理
Novate 申请挂失
操作完毕
开始受理
Novate 额外业务
操作完毕

注意:

在Client中,每调用一次bank.applyBank()、bank.lostBank()、bank.extraBank()都会调用一次动态代理的invoke()方法中的 method.invoke()方法

2. IBank接口添加额外功能


如果有银行卡丢失或者还有一些额外的其他功能,那么就只需要在IBank接口中添加对应方法,然后在动态代理对象 BankInvocationHandler中调用对应方法即可,比如现在新增了 挂失银行卡和其他额外功能,lostBank()、extraBank()方法,实现思路如下:
1>:首先在IBank接口中 新增lostBank()、extraBank()方法;
2>:然后让Man实现 IBank接口,然后实现所有方法;
3>:最后在 Client测试代码中,使用 被代理对象 man调用所有新增方法即可;
具体实现代码如上,

3. 动态代理优点


动态代理的优点就是:
如果说后期 IBank接口中需要添加任何方法,可以直接去IBank接口中添加,然后让被代理对象Man实现 IBank接口,然后实现里边所有方法,然后在最后测试的 Client中使用 被代理对象man调用所有方法即可,对动态代理的类BankInvocationHandler没有任何影响,这个类不需要修改任何代码,这样就可以完全的避免静态代理的这个弊端;

你可能感兴趣的:(代理设计模式(三) - 动态代理)