代理模式回顾

之前的两篇文章《Java反射——Proxy和动态代理》《CGLIB动态代理原理分析》,介绍了代理模式,引出动态代理。然后分别介绍了常用的JDK动态代理和CGLIB动态代理。本篇再次回顾下关键点。

1.代理模式

先上类图

在这里插入图片描述

  1. 控制对象访问
  2. 代理类和被代理类都实现了同一接口,代理类持有被代理类的引用。

静态代理十分简单易懂,但随着被代理对象的增加,代理类也会随之增加。但每个代理类所做的工作又十分类似。为了解决这一问题,引出了动态代理。

动态代理

如上所述,抽象出了公共的代理类。在运行时,动态生成具体的代理类。
JDK动态代理,引入Proxy类来生成代理类。真正的代理类为$Proxy0。

Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);

工具类Proxy,根据传入的目标类的信息,生成代理类$Proxy0。

举例说明:
被代理类:AgencyServiceImpl
共同实现接口:AgencyService
代理类:$Proxy0

保存生成的代理类Class文件

        FileOutputStream out = null;
            try {
                byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", AgencyServiceImpl.class.getInterfaces());
                out = new FileOutputStream(filePath[0] + "$Proxy0.class");
                out.write(classFile);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.flush();
                        out.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

$Proxy0


public final class $Proxy0 extends Proxy implements AgencyService {
    private static Method m1;
    private static Method m4;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

   static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("com.family.service.AgencyService").getMethod("queryAgency", Class.forName("com.family.model.AgencyInfo"));
            m3 = Class.forName("com.family.service.AgencyService").getMethod("test");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }

    public final List queryAgency(AgencyInfo var1) throws  {
        try {
            return (List)super.h.invoke(this, m4, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    ......
}

对应完整类图如下:
在这里插入图片描述
CGLIB动态代理类似,生成的$Proxy0也基本一致。只是生成的方式不太一样。

2.比较

1)装饰者

装饰属于行为型模式,目的在于动态将责任(行为)加到对象上。

类图
在这里插入图片描述

a. 装饰者和具体对象有共同父类
b. 装饰者持有父类引用
c.以上两者设计,都为了方便的进行一层层的包装。

2)适配器

解决兼容问题

在这里插入图片描述

a. 适配器隔绝了客户(Client)和被适配者(Adaptee)【封装】
b. 适配器承担了中间转换的角色

3.小结

从根源出发,根据需求,一步一步演变推进。
对于设计模式的比较,要先从设计初衷出发。了解设计的精髓之处,不停留在一知半解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值