在众多的设计模式当中,代理设计模式算的上是一种比较重要的设计模式,而且在很多地方都可以找到它的身影,同样的在现实生活当中,我们也随处可见它的踪影。比如,你需要找房子,通过中介能够快速的找到你自己想要的房子,其中中介就充当了一种代理的功能;又比如,老板拖欠工资,你找律师帮你打官司拿回工资也是一种代理模式(这个例子在接下来可以看见)。好了,废话不多说了,我们直接进入主题吧。
定义:
为其他对象提供一种代理以控制对这个对象的访问
静态代理:
对于静态代理而言,我们需要知道它的组成有哪些部分:
1》被代理的具体类
2》代理类
3》执行过程
这样说的话可能会有点抽象,下面我们通过一个简单例子来进行说明,以上面的律师帮你打官司拿回工资这种现实当中的例子来进行说明
/**
* 接口(用来描述具体类需要执行的方法)
*/
public interface ILawsuit {
// 提交诉讼申请
void submit();
// 进行举证
void burden();
// 进行答辩
void defend();
// 完成诉讼
void finish();
}
/**
* Lily的诉讼请求
*/
public class Lily implements ILawsuit {
@Override
public void submit() {
System.out.println("老板拖欠工资,请求法院强制执行");
}
@Override
public void burden() {
System.out.println("这是每个月的工资流水和劳务合同");
}
@Override
public void defend() {
System.out.println("证据充足,无须多言");
}
@Override
public void finish() {
System.out.println("法院强制执行,通知7个工作日返回拖欠工资");
}
}
这个就是被代理的具体类,用于执行最后的操作
/**
* 静态代理类
*/
public class RealProxy implements ILawsuit {
private ILawsuit lawsuit;
public RealProxy(ILawsuit lawsuit) {
this.lawsuit = lawsuit;
}
@Override
public void submit() {
lawsuit.submit();
}
@Override
public void burden() {
lawsuit.burden();
}
@Override
public void defend() {
lawsuit.defend();
}
@Override
public void finish() {
lawsuit.finish();
}
}
注意第8行,我采用的是接口而非具体类,这样写的目的即遵循了开闭原则又提高了代码的扩展性,当然这个类就是我们的代理类
// 具体的执行对象
ILawsuit jack = new Jack();
// 代理对象
ILawsuit realProxy = new RealProxy(jack);
// 执行
realProxy.submit();
realProxy.burden();
realProxy.defend();
realProxy.finish();
到这里简单的静态代理模式就结束了,总结一下:
创建一个静态代理对象,在对象中持有被代理类的实例,然后实现被代理类相同的接口,最后执行的时候由代理类触发被代理类的操作
有木有很简单,当然到了这里可能有的同学就会有疑问了,如果我有10个人要打官司,那我是不是要写10个相同的类,有没有更简便的方法呢?答案肯定是有的,就是我们的动态代理了。我们发现,在执行之前我们的被代理类已经编码好了,而动态代理和静态代理最大的区别就在于动态代理在执行的时候才生成对应的被代理类然后去执行对应的方法,那么我们现在继续往下看一起来看看动态代理吧
动态代理:
动态代理顾名思义动态生成代理对象,所以我们的代理对象不再是我们自己手动编码,而是借助于系统定义好的接口去动态生成,具体的变现为:实现InvocationHandler接口,重写里面的invoke方法,通过反射去执行对应的操作
我们还是以上面的例子为例,首先修改我们的代理类
/**
* 动态代理方法,在具体的执行的时候去代理具体的类
*/
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
最后的执行
// 构造一个具体类
ILawsuit jack = new Jack();
// 构造一个动态代理
DynamicProxy dynamicProxy = new DynamicProxy(jack);
// 获取被代理类的ClassLoader
ClassLoader loader = jack.getClass().getClassLoader();
// 动态构造一个代理者对象
ILawsuit lawsuit = (ILawsuit) Proxy.newProxyInstance(loader, new Class[{ILawsuit.class}, dynamicProxy);
// 律师提交诉讼申请
lawsuit.submit();
// 律师进行举证
lawsuit.burden();
// 律师进行答辩
lawsuit.defend();
// 完成诉讼
lawsuit.finish();
最后的执行结果为:
包工头拖欠农民工工资
每个月的工作时长
包工头名下财产
法院进行强制执行
相对于静态代理而言,动态代理逻辑更为清晰,而且我们的代理类写法也是固定的(代码量也很少),那么对于静态代理和动态代理而言,它们之间的区别是什么呢?
静态代理和动态代理对比:
1》静态代理的代理者的代码由程序员自己或者通过一些自动化工具生成固定的代码再进行编译,即在代码运行前代理类的class编译文件就已经存在
2》动态代理与静态代理相反,通过反射机制动态地生成代理者的对象
3》动态代理比静态代理代码量更少,更简洁