说明
代理模式,顾名思义,使用代理类对原类进行扩展。
UML
代码
以NetWork为上网接口为例,默认为CommonNet,实现NetWork接口,然后可以通过ProxyNet代理类来对原CommonNet进行扩展,代码如下。
通用接口
/**
* @author ctl
* @date 2021/1/18
* 通用接口
*/
public interface NetWork {
void online();
}
默认实现类
/**
* @author ctl
* @date 2021/1/18
* 默认实现类
*/
public class CommonNet implements NetWork {
@Override
public void online() {
System.out.println("上网");
}
}
代理类,实现通用接口,并对原CommonNet进行扩展
/**
* @author ctl
* @date 2021/1/18
* 代理类
*/
public class ProxyNet implements NetWork {
private NetWork commonNet;
public ProxyNet(NetWork commonNet) {
this.commonNet = commonNet;
}
@Override
public void online() {
before();
commonNet.online();
after();
}
private void after() {
System.out.println("关闭代理服务器");
}
private void before() {
System.out.println("开启代理服务器");
}
}
测试类
/**
* @author ctl
* @date 2021/1/18
*/
public class ProxyMain {
public static void main(String[] args) {
// 代理前
NetWork commonNet = new CommonNet();
commonNet.online();
System.out.println("---------分割线---------");
// 代理后
NetWork netWork = new ProxyNet(commonNet);
netWork.online();
}
}
结果
可以看出使用代理后,对原online方法进行了前后的扩展。
总结
代理模式其实分为静态代理和动态代理,上述是静态代理的实现方式,被代理的类是固定的。动态代理则不是固定的。
众多常用的开源框架中都使用了动态代理,比如mybatis的mapper实现类,spring的aop等等。
动态代理通常使用jdk的动态代理和cglib动态代理,区别是使用jdk代理的类要实现接口,而cglib代理的类不能被final修饰,因为cglib是通过继承关系来实现的代理,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。
关于这两种动态代理的实现方式,之前我在手写简版“Spring”,基于自定义注解实现IOC和AOP这篇文章中实现过,就不再重复写了。