结构型模式之代理模式
代理模式:访问对象不适合直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
角色:
- 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
- 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
- 代理(Proxy)类:提供与真实主题相同的接口,其内部包含对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
一般代理分三种模式:
- 静态代理:代理类实现抽象主题类,聚合真实主题类,在实现抽象主题类中的业务方法中调用真实主题类进行扩展。
- JDK动态代理:JDK动态代理通过Proxy.newProxyInstance方法进行动态代理,其中又主要用到了InvocationHandler接口中的invoke方法;聚合真实主题类,方法返回值为抽象主题类。本质是与真实主题类实现共有接口,通过多态性实现开闭原则。
/**
* 代理工厂,生产代理对象
* 代理类也实现了对应的接口
*/
public class ProxyFactory {
// 目标对象
TrainStation trainStation = new TrainStation();
// 获取代理对象的方法。
public SellTickets getProxyObject(){
// 返回代理对象即可
return (SellTickets) Proxy.newProxyInstance(trainStation.getClass().getClassLoader(),
trainStation.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable {
System.out.println("代理点收取服务费");
// 执行目标对象的方法
Object invoke = method.invoke(trainStation, args);
return invoke;
}
});
}
}
- CGLib动态代理:为JDK动态代理进行很好的补充,若目标代理类没有实现任何共有接口,JDK动态代理无法实现。CGLib动态代理需要实现MethodInterceptor接口,聚合真实对象类,实现intercept方法进行动态代理。
/**
* 代理对象工厂 -- 获取代理对象
* 代理对象 -- 目标对象的子类
*/
public class ProxyFactory implements MethodInterceptor {
// 声明目标对象
TrainStation trainStation = new TrainStation();
public TrainStation getProxyObject() {
// 创建Enhancer对象,类似于JDK代理中的Proxy类
Enhancer enhancer = new Enhancer();
// 设置父类的类对象
enhancer.setSuperclass(TrainStation.class);
// 设置回调函数
enhancer.setCallback(this);
// 创建代理对象
TrainStation proxyObject = (TrainStation) enhancer.create();
return proxyObject;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代售点收取费用");
// 调用目标
Object invoke = method.invoke(trainStation, objects);
return invoke;
}
}
JDK动态代理与CGLib动态代理区别
JDK动态代理的思想是通过与真实主题对象实现共有接口,调用代理方法,代理方法中可以对真实主题对象进行扩展和调用等操作,达到代理的模式。
CGLib动态代理思想,通过继承真实对象,实现MethodInterceptor中的intercept方法对真实主题对象进行代理。