代理模式-JAVA设计模式

设计模式相关文章

----单例模式原理-JAVA设计模式
----工厂模式原理-JAVA设计模式
代理模式原理-JAVA设计模式
----建造者模式(Bulider模式)详解—JAVA设计模式

代理方式

  • 代理模式分为2种
  1. 静态代理
  2. 动态代理

一、静态代理

1、介绍

1.1、定义

给目标角色提供一个代理角色,并由代理角色控制对目标角色的引用

1.2、作用

通过引入代理角色的方式来间接访问目标角色

2、 案例解析

2.1、 流程结构

房东出租房子的例子,3个角色:房东----中介----租客

  1. 抽象角色----房子出租信息(Rent)
  2. 真实对象----房东(Host)
  3. 代理类(代理角色)----中介(StaticProxy)
  4. 租客----(Client)
2.2、 代码实现

1、抽象角色----房子出租信息(Rent)

/**
 * 抽象角色---租房
 *
 * @Auther: curry
 * @Description:
 */
public interface Rent {

    public void rent();
}

2、真实对象—房东(Host)

/**
 * 真实角色---房东---要出租房子
 *
 * @Auther: curry
 * @Description:
 */
public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("出租房子");
    }
}

3、 代理类(代理角色)----中介(StaticProxy)



/**
 * 静态代理角色:中介
 */
public class StaticProxy implements Rent {

    private Host host;

    //无参构造
    public  StaticProxy() {

    }

    //有参构造
    public  StaticProxy(Host host) {
        this.host=host;
    }

    //租房
    @Override
    public void rent() {
        see();
        host.rent();
        fare();
    }

    //看房
    public void see() {
        System.out.println("带租客看房");
    }

    //中介费
    public void fare() {
        System.out.println("收中介费");
    }
}

4、 租客----(Client)

/**
 * 租客----(Client)
 *
 * @Auther: curry
 * @Description:
 */
public class Client {

    public static void main(String[] args) {

        //真实角色--- //房东要出租房子
        Host host=new Host();

        //代理实例--中介帮助房东
        StaticProxy staticProxy = new StaticProxy(host);

        //租客去找中介!
        staticProxy.rent();
    }
}


5、 测试打印

在这里插入图片描述

2.3、分析

在这个过程中,租客直接接触的就是中介,租客不用接触房东,依旧租到了房东的房子,通过代理,这就是所谓的代理模式

3、优缺点

3.1、优点
  1. 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
  2. 公共的业务由代理来完成 . 实现了业务的分工
  3. 公共业务发生扩展时变得更加集中和方便
3.2、缺点
  1. 由于在租客和真实角色(房东)之间增加了代理角色(中介),因此会造成请求的处理速度变慢
  2. 1个静态代理 只服务1种类型的目标角色(房东),若要服务多类型的目标角色,则需要为每种目标角色都实现一个静态代理角色,代码类的增加,从而增加了系统实现的复杂度
3.3、总结

为了解决静态代理的缺点,代理角色和目标角色一对一的关系,才有动态代理的出现

二、动态代理

1、介绍

1.1、定义
  1. 动态代理的角色和静态代理的一样
  2. 动态代理的代理类是动态生成的,不同于静态代理是直接生成的
  3. 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
  • 基于接口的动态代理----JDK动态代理
  • 基于类的动态代理–cglib
1.2、作用

通过引入代理角色的方式来间接访问目标角色

2、 案例解析

2.1、基于接口的动态代理----JDK动态代理

JDK的动态代理需要了解两个类
核心 : InvocationHandler 和Proxy

  • invocationHandle接口----调用处理程序

是由代理实例的调用处理程序实现的接口,每个代理实例都有一个关联的调用处理程序,当在代理实列上调用方法时,方法调用将被 分配到其调用处理程序的invoke方法(这一个是JDK翻译给出来的解释),------简单的来理解就是代理类要实现invocationHandle接口并重写它的invoke方法

  • Proxy方法

提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的代理类的超类(也是JDK翻译给出来的解释,后面一句非常拗口)

2.2、 流程结构
  1. 抽象角色----房子出租信息(Rent)
  2. 真实对象----房东(Host)
  3. 动态代理类----代理角色(DynamicProxy)
  4. 租客----(Client)
2.3、 代码实现

1、抽象角色----房子出租信息(Rent)

/**
 * 抽象角色---租房
 *
 * @Auther: curry
 * @Description:
 */
public interface Rent {

    public void rent();
}

2、真实对象—房东(Host)

/**
 * 真实角色---房东---要出租房子
 *
 * @Auther: curry
 * @Description:
 */
public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("出租房子");
    }
}

3、动态代理类----代理角色(DynamicProxy)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理
 * 需要实现invocationHandle接口
 */
public class DynamicProxy implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理类
    public Object getProxy(){
        //this.getClass().getClassLoader(),当前对象的类加载器
        //rent.getClass().getInterfaces()被代理的接口
        //当前对象
        Object newProxyInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        return newProxyInstance;
    }

    /**
     * 处理代理实例并返回结果
     * @param o 调用该方法的代理实例
     * @param method 所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口
     * @param objects 包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        see();
        //使用ORM反射机制实现,动态代理的本质
        Object invoke = method.invoke(rent, objects);
        fare();
        return invoke;
    }
    //看房
    public void see() {
        System.out.println("带租客看房");
    }

    //中介费
    public void fare() {
        System.out.println("收中介费");
    }
}

4、 租客----(Client)

package api.web.proxy.dynamicProxy;

/**
 * 租客----(Client)
 *
 * @Auther: curry
 * @Description:
 */
public class Client {

    public static void main(String[] args) {
        //真实角色
        Host host=new Host();

        //代理实例
        DynamicProxy dynamicProxy = new DynamicProxy();

        //调用程序处理角色 来处理我们要调用的接口对象
        dynamicProxy.setRent(host);
        Rent proxy = (Rent)dynamicProxy.getProxy();
        proxy.rent();
    }
}

5、 测试打印

在这里插入图片描述

3、优缺点

3.1、优点
  1. 只需要1个动态代理类就可以解决创建多个静态代理的问题,避免重复、多余代码
  2. 设计动态代理类(DynamicProxy)时,不需要显式实现与目标对象类(Host)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现
  3. 在使用时(调用目标角色方法时)才会动态创建动态代理类 & 实例,不需要事先实例化
3.1、优点
  1. 效率低
    相比静态代理中 直接调用目标角色方法,动态代理则需要先通过Java反射机制 从而 间接调用目标角色方法
  2. 应用场景局限
    因为 Java 的单继承特性(每个代理类都继承了 Proxy 类),即只能针对接口 创建 代理类,不能针对类 创建代理类
3.3、总结
  1. 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
  2. 公共的业务由代理来完成 . 实现了业务的分工
  3. 公共业务发生扩展时变得更加集中和方便
  4. 一个动态代理 , 一般代理某一类业务
  5. 一个动态代理可以代理多个类,代理的是接口
3.4、应用场景
  1. 具体应用场景:日志记录、性能统计、安全控制、异常处理等

设计模式相关文章

----单例模式原理-JAVA设计模式
----工厂模式原理-JAVA设计模式
代理模式原理-JAVA设计模式
----建造者模式(Bulider模式)详解—JAVA设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值