代理模式:为其他对象提供一种代理以控制对对象的访问
主要解决:直接访问对象时带来的问题,比如,要访问的对象在远程机器上,有些对象由于某些原因,创建开销很大,或者操作需要安全控制,或者需要进程外的访问。直接访问会给使用者带来很多麻烦,因此可以在访问对象时加上一个对此对象的访问层。
应用实例:windows快捷方式,spring aop
优点:1 职责清晰 2 高扩展性 3 智能化
缺点:1 在客户端和真实对象之间增加了代理对象,有些类型的代理模式可能会造成请求处理速度变慢。2 实现代理模式需要额外的工作。有些代理模式的实现非常复杂。
使用场景:1. 远程代理 2. 虚拟代理 3. Copy-on-write代理 4. 保护代理(Protect or Access)5. Cache代理 6. 防火墙代理 7. 同步化代理(Synchronization) 8. 智能引用代理(smart reference)
代理模式和适配器模式的区别:适配器模式主要改变所考虑对象的接口,代理模式不能改变所代理类的接口
代理模式和装饰器模式的区别:装饰器模式是为了增强功能,代理模式是为了加以控制。
静态代理实例:
代码语言:javascript复制public interface Movable {
void move();
}
代码语言:javascript复制public class TankTimeProxy implements Movable {
private Movable tank;
public TankTimeProxy(Movable tank){
this.tank=tank;
}
@Override
public void move(){
long start=System.currentTimeMillis();
System.out.println("start time : " start);
tank.move();
long end=System.currentTimeMillis();
System.out.println("end time : " end);
System.out.println("spend all time :" (end-start)/1000 "s.");
}
}
代码语言:javascript复制public class TankLogProxy implements Movable{
private Movable tank;
public TankLogProxy(Movable tank){
this.tank=tank;
}
@Override
public void move(){
System.out.println("tank move start");
tank.move();
System.out.println("tank move end");
}
}
代码语言:javascript复制Movable target=new TankLogProxy(new TankTimeProxy(new Tank()));
target.move();
动态代理实例:
代码语言:javascript复制public class MyTimeProxyInvokeHandler implements InvocationHandler {
private Object target;
public MyTimeProxyInvokeHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
long start=System.currentTimeMillis();
System.out.println("start time :" start);
method.invoke(target,args);
long end=System.currentTimeMillis();
System.out.println("end time : " end);
System.out.println("spend all time : " (end-start)/1000 "s.");
return null;
}
}
代码语言:javascript复制Movable tank=new Tank();
MyTimeProxyInvokeHandler myTimeProxyInvokeHandler=new MyTimeProxyInvokeHandler(tank);
Movable tankProxy=(Movable)Proxy.newProxyInstance(tank.getClass().getClassLoader(),tank.getClass().getInterfaces(),myTimeProxyInvokeHandler);
tankProxy.move();
这种方式为JDK的Proxy代理实现,目标类与代理类实现相同的接口,目标类不存在接口,只能使用CGLIB来解决。
CGLIB代理生成原理是生成目标类的子类,子类是增强过的,子类对象就是代理对象。
CGLIB实现代理模式:
代码语言:javascript复制public class Tank2 {
public void move(){
System.out.println("Tank Moving ,....");
try{
Thread.sleep(new Random().nextInt(5000));
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
代码语言:javascript复制public class MyTimeProxyInvokeHandler implements InvocationHandler {
private Object target;
public MyTimeProxyInvokeHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
long start=System.currentTimeMillis();
System.out.println("start time :" start);
method.invoke(target,args);
long end=System.currentTimeMillis();
System.out.println("end time : " end);
System.out.println("spend all time : " (end-start)/1000 "s.");
return null;
}
}
代码语言:javascript复制Tank2 proxyTank=new MyCglibFactory(new Tank2()).myCglibCreator();
proxyTank.move();
参考:
菜鸟教程-代理模式
代理模式