介绍
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
类图说明
咱们来看一个简单的代理模式的例子,还是用我们一直用的车的例子。首先创建一个车工厂的接口,然后创建两个实现类分别实现它,一个是我们的宝马车工厂,还有一个是宝马车代理工厂,代理工厂中会声明一个宝马车工厂的对象,buildCar的时候会调用它去创建宝马车。所以代理类就是这么简单,对外开放代理类对象,buildCar的时候其实还是调用了宝马车工厂去创建了宝马。当然代理类是可以在调用真正对象的时候前后做一些增强的,这可能才是实用的地方吧。
代码示例
文件结构如下:
代码示例如下:
public interface CarFactory {
void buildCar();
}
public class BMWFactory implements CarFactory {
private String name;
public BMWFactory(String name){
this.name = name;
}
@Override
public void buildCar() {
System.out.println(String.format("%s车创建中",this.name));
}
}
public class BMWProxyFactory implements CarFactory {
private String name;
private BMWFactory factory;
public BMWProxyFactory(String name){
this.name = name;
}
@Override
public void buildCar() {
factory = new BMWFactory(this.name);
factory.buildCar();
}
}
public class ProxyPattern {
public static void main(String[] args){
BMWProxyFactory proxyFactory = new BMWProxyFactory("宝马X7");
proxyFactory.buildCar();
}
}
运行结果如下:
应用场景
- 远程代理
- 虚拟代理
- 保护(Protect or Access)代理
- Cache代理
- 防火墙(Firewall)代理
- 同步化(Synchronization)代理
优缺点
优点
- 职责清晰
- 高扩展性
- 智能化
缺点
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂
拓展
讲到代理不得不提动态代理,也是我们用的最多最熟悉的设计模式,其中Spring AOP就是动态代理的实现。还是一样,上个图先,将我们上副图做下改造如下:
在类图中增加了一个InvocationHandler接口和MyInvocationHandler类,作用就是产生一个对象的
代理对象,其中InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行代理。
我们来看程序,接口保持不变,实现类也没有变化.。
代码如下:
public class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public MyInvocationHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(this.obj, args);
return result;
}
}
public class DynamicProxyPattern {
public static void main(String[] args){
BMWFactory bmwFactory = new BMWFactory("宝马X7");
InvocationHandler handler = new MyInvocationHandler(bmwFactory);
CarFactory proxy = (CarFactory) Proxy.newProxyInstance(bmwFactory.getClass().getClassLoader(),bmwFactory.getClass().getInterfaces(),handler);
proxy.buildCar();
}
}
结果如下:
是的,运行结果和我们上述定制实现的代理类的效果一致,这就是动态代理。在此先做个简单介绍,后续需要再进一步对动态代理进入深入了解,包括它的设计原理,代码实现,jdk动态代理,cglib动态代理,包括最典型的aop源码阅读,将是我们的目标,加油。