代理模式(Proxy Pattern)__浅谈与装饰器模式的区别

代理模式(英语:Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。

 

代理模式和装饰器模式的共同点

  不改变原有组件的情况下增强其功能

 

代理模式和装饰器模式的差异

  代理模式可以实现延迟加载,即在需要时才真正创建原有组件,而不是在创建代理时就立即创建原有组件,这对于提高性能和节省资源是有益的。(延迟加载

  代理模式更着重于环绕组件的方式(代理行为)的附加动作,装饰器模式则是在组件基础上做固有拓展(自身行为)。

  代理模式适用于更灵活、更复杂、更抽象的功能增强场景,装饰器模式适用于直接简洁的功能增强场景。

代码演示(Java)

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proxy.invokeSuper(obj, args);
        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;
        System.out.println("Method " + method.getName() + " execution time: " + elapsedTime + " ms");
        return result;
    }

}

// ------------------------------

public class Cat {

    public void meow(){
        System.out.println("meow~~~meow~~~");
    }
}

// ------------------------------

import org.ashe.demo.domain.Cat;
import org.ashe.demo.proxy.ProxyFactory;
import org.springframework.cglib.proxy.Enhancer;

public class Ashe {

    public static void main(String[] args) {
        // 创建Enhancer对象
        Enhancer enhancer = new Enhancer();
        // 设置被代理类的类对象
        enhancer.setSuperclass(Cat.class);
        // 设置回调函数
        enhancer.setCallback(new ProxyFactory());
        // 创建代理对象
        Cat proxy = (Cat) enhancer.create();
        // 调用代理对象的方法
        proxy.meow();
    }

}

 以上代理使用CGLIB动态代理实现了对Cat对象meow方法的监控,记录了meow方法的执行耗时时间。且可以看出enhancer.create()方法执行时,代理对象poxy才会生成,体现了其延迟加载的特性。

值得注意的是被动态代理后,代理对象的所有行为都会被代理,因此给Cat类增加新方法时,代理对象的新方法也会被监控执行耗时。

 

为什么要代理分为静态代理和动态代理?

  1. 减少重复代码: 动态代理可以在运行时动态地生成代理对象,不需要手动编写大量的代理类,从而减少了代码量。

  2. 灵活性: 动态代理可以代理任意接口或类,不需要为每个被代理的类或接口编写一个对应的代理类,提高了系统的灵活性。

  3. 适应性: 动态代理可以适应接口或类的变化,不需要修改代理类的代码。这种松耦合性使得系统更容易维护和扩展。

 

讨论CGLIB动态代理时,就很容易联想到AOP(面向切面编程),其实Spring AOP实现就是基于代理模式(JDK动态代理+ CGLIB 动态代理),因此在使用Spring AOP切面编程的时候,其实是比较厚重的,因为它对整个Controller做了代理,因此IOC中存在代理Controller对象和原生Controller对象两份实例,因此在应用简单场景的切面编程时,从降低复杂度出发,可以优先考虑代理模式等其他更简洁的方案。

 
posted @ 2024-03-19 21:03  Ashe|||^_^  阅读(29)  评论(0编辑  收藏  举报