代理模式

2019-04-18 16:45:15 浏览数 (2)

代理模式:为其他对象提供一种代理以控制对对象的访问

主要解决:直接访问对象时带来的问题,比如,要访问的对象在远程机器上,有些对象由于某些原因,创建开销很大,或者操作需要安全控制,或者需要进程外的访问。直接访问会给使用者带来很多麻烦,因此可以在访问对象时加上一个对此对象的访问层。

应用实例: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();

参考:

菜鸟教程-代理模式

代理模式

0 人点赞