java设计模式---代理模式详解

简介: java设计模式---代理模式详解

一,代理模式概念

1,什么是代理模式

Proxy Pattern,代理模式是指为其他对象提供一种代理,以控制对这个对象的访问,代理对象在客户端,服务端以及目标对象之间起到中介作用。并且是属于一种结构型模式


2,代理模式的应用场景

1,房产中介,不管是租房还是买房都是可以去找这个中介


2,快递小哥,通过快递小哥实现将商品从商户送到用户手上


3,黄牛党,12306买不到票,或者演唱会之类的,通过这个黄牛购票


4,代理服务器,翻墙等


3,例如一个租房场景

fd915665b360445fba5657c8a3906e9e.png

这个房屋和中介他们做一样的事情,就是租房或者卖房给用户

中介是房东的代理,房东是中介的目标。然后用户可以先找中介,中介再找房东


4,开发场景

1,a方法调用c方法不让,增加一个b方法,让a调用b,b去调用c

2,如最近的controller调用service,service调用mapper这种也是利用这种思想

3,如登录时要短信验证,通过这个第三方实现


5,代理模式的作用

1,功能增强,可以在原有的功能上能可以增加额外的功能


2,控制访问,可以通过这个代理类来实现能不能到访问这个目标类


二,静态代理

2.1,静态代理举例

代理类手动实现,并且需要代理的对象是确定的,固定的。例如一个买手机的一个案例来描述这个静态代理。

5f230b235d09400fae77010b2a00d4ad.png


就是在买手机的时候需要去手机店里面买手机,而不是直接去找厂商。因此这个手机店就是作为一个代理类,这个手机厂商就是对应的目标类,其类图如下。


接下来就编写一个接口,用来统一厂家和这个手机店都去卖手机的一个方法

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 17:39
 * 代理类和这个目标类都要走的一件事情,卖手机
 */
public interface PhoneSell {
    //卖手机并返回价钱  amount要的数量
    public Double sell(Double amount);
}

接下来编写一个厂家卖手机的一个方法

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 17:54
 * 厂商销售手机
 */
public class Factory implements PhoneSell {
    /**
     * 卖手机,1800一部
     */
    @Override
    public Double sell(Double amount) {
        Double price = amount * 1800;
        return price;
    }
}

再编写一个手机店的实体类,这个代理类不做具体的事情,会把这个卖手机的事情交给这个厂商去做,并且在这个代理类里面,在原先的基础上可以实现一个增强。

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 17:55
 * 商店购买,代理类只负责中转,不做具体的买卖,但是可以做增强
 */
public class Shop implements PhoneSell {
    //构建一个厂商对象
    private Factory factory = new Factory();
    @Override
    public Double sell(Double amount) {
        //商家转发给厂家卖手机的信息
        double price = factory.sell(amount);
        //商家需要赚钱
        price = price +  price * 0.2;
        // ... 可以做很多事情,都是增强的意思
        //返回需要的价钱
        return price;
    }
}

然后在写个测试方法,就可以购买一部手机了。

//用户手机店购买手机
Shop shop = new Shop();
Double price = shop.sell(1);
System.out.println(price);

这就是简单的实现了一个静态代理。其实就很类似经常写的controller,service,mapper。这个service层就是作一个转发,数据交互还是要交给mapper层处理,并且这个业务逻辑都是在这个service层处理,从而在mapper层基础上多写了一些业务逻辑,得到了增强功能。


2.2,静态代理中代理类的作用

1,目标类中的方法调用


2,功能增强


1,每个代理类只能代理一个固定的目标类,如果目标类会有多个商店或者厂家,那么就需要增加很多这个代理类


2,如果厂家增加或者修改一个功能,会影响众多的实现类,厂家类和代理类都需要进行一个修改


三,动态代理

为了解决这个代理数量很多,修改接口方法会影响到这个代理类和目标类的问题,从而进入了这个动态代理的这个解决方案。


3.1,什么是动态代理

在程序执行的过程中,利用这个jdk的反射机制,创建这个代理类的对象,并动态指定这个代理目标类。


3.2,动态代理优点

1,不用创建代理类


2,可以给不同的目标随时创建动态代理


3.3,动态代理实现方式

3.3.1,jdk动态代理

通过这个java自带的反射包中的类和接口实现动态代理的功能。里面主要有三个类,分别是InvocationHandler,Method,Proxy三个类,通过这个三个类来实现一个动态代理。要求这个jdk动态代理必须要有接口,如果没有则实现不了。


InvocationHandler接口,里面有一个invoke方法,代理类要完成的这个功能就写在这个方法里面

Method类:主要是获取这个目标类中的方法。Method.invoke()实现

Proxy类:核心的对象,创建代理对象,newProxyInstance()创建代理对象


依旧是使用之前的卖手机的场景,需要用到上面的几个对象。原理相当于将之前写死的一个代理类只能对应一个目标类,改成这个代理类变成一个动态的形式,一个目标类想要一个代理类时,可以通过一个模板来实现,而不需要去重新创建多个代理类。jdk动态代理代码实现如下


1,依旧需要一个主接口,用来规范这个目标类和代理类做一样的事情

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 17:39
 * 代理类和这个目标类都要走的一件事情,卖手机
 */
public interface PhoneSell {
    //卖手机并返回价钱  amount要的数量
    public Double sell(Double amount);
}

2,依旧需要一个目标对象

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 17:54
 * 厂商销售手机
 */
public class Factory implements PhoneSell {
    /**
     * 卖手机,1800一部
     */
    @Override
    public Double sell(Double amount) {
        Double price = amount * 1800;
        return price;
    }
}

3,和静态代理不一样的是,动态代理不需要具体的代理类,而是通过实现这个 InvocationHandler这个接口来这个jdk的动态代理。会通过外部的传参来确定成为哪个类的动态代理对象,通过这个方法来确定需要代理这个对象的哪个方法。并且会通过这个invoke方法来获取目标类对象里面的方法,然后获取到结果之后对这个类进行一个功能的增强。最后将执行结果返回

/**
 * @Author: zhenghuisheng
 * @Date: 2022/9/10 20:38
 * jdk动态代理,必须实现InvocationHandler这个接口,然后获取到一个jdk动态代理类
 * 主要是为了调用目标方法,实现功能增强
 */
public class ProxyInvocationHandler implements InvocationHandler {
    //目标对象
    private Object target = null;
    //外部实例化时需要传入这个目标对象
    //传入的是谁就给谁创建动态代理
    public ProxyInvocationHandler(Object target){
        this.target = target;
    }
    /**
     * 这个方法就是代理类里面的代理方法
     * @param proxy :代理类,需要外部手动传入需要代理的类
     * @param method : 目标方法,可能一个类里面会有多个方法
     * @param args : 目标方法参数,对应目标方法里面的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = null;
        //目标方法执行
        //第一个是目标对象,第二个是目标参数
        //这个目标对象是一个动态的,因此需要外面传入
        object = method.invoke(target,args);
        //在获取到这个目标方法之后,可以对这个目标方法进行一个增强功能
        if (object != null){
            //外部传入这个sell的这个方法,那么执行这个方法的返回值类型为Double
            Double price = (Double)object;
            //手机店获取利润,功能增强
            price = price + price* 0.2;
            object = price;
        }
        return object;
    }
}

4,在外部需要向ProxyInvocationHandler的构造方法中传入目标对象,并且通过这个Proxy类的newProxyInstance方法来获取这个代理类,然后通过这个获取的代理类执行对应的方法。

//1,创建目标对象
PhoneSell factory = new Factory();
//2,创建proxyInvocationHandler对象
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(factory);
//3,创建动态代理对象
/**
 * newProxyInstance(ClassLoader loader,
 *                 Class<?>[] interfaces,
 *                 InvocationHandler h)
 */
//获取目标类类加载器
ClassLoader classLoader = factory.getClass().getClassLoader();
//获取类对应的接口
Class<?>[] interfaces = factory.getClass().getInterfaces();
//通过反射的形式获取代理类
//强行转换成对应的接口
PhoneSell proxy = (PhoneSell)Proxy.newProxyInstance(classLoader, interfaces, proxyInvocationHandler);
//购买数量
Double sellPrice = proxy.sell(4);
System.out.println(sellPrice);

这样的jdk动态代理的就实现好了,里面的步骤都是固定的


3.3.2,cglib动态代理

通过第三方的库来实现动态代理,会创建一个代理对象。


原理:通过继承目标类,创建他的子类,在子类中重写父类中同名的方法,实现功能的修改。cglib目标类不能使用final,只要子类可以继承即可。


cglib相对而言开发中用的比较少,了解原理即可


四,总结

代理模式主要分为静态代理和动态代理。


静态代理中主要有一个目标类和一个代理类,其两个类都要实现一个共同的接口,做一样的事情,代理对象主要负责转发和功能增强,其具体做事情的还是这个目标对象。静态代理不足的地方在于一个代理类只能绑定一个目标类,如果一个目标类或者多个目标类需要多个代理对象,那么就需要创建大量的代理对象,并且如果接口类里面有一点点的功能的改动,那么这个目标类和代理类就会有大量的改动。


动态代理解决了这个静态代理的问题,在要创建很多代理对象方面,通过一个动态代理对象实现。动态代理主要有jdk的动态代理和cglib的动态代理,jdk动态代理是java里面自带的库,而cglib使用的是第三方库。jdk动态代理主要是通过这个InvocationHandler接口来获取这个目标类和实现代理类的功能增强,并通过反射的方式,获取到这个代理类对象,最后通过这个代理对象获取到对应的方法


相关文章
|
1天前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
|
1天前
|
设计模式 安全 网络协议
【设计模式】代理模式例子解析
【设计模式】代理模式例子解析
9 2
|
1天前
|
设计模式 JavaScript 算法
js设计模式-策略模式与代理模式的应用
策略模式和代理模式是JavaScript常用设计模式。策略模式通过封装一系列算法,使它们可互换,让算法独立于客户端,提供灵活的选择。例如,定义不同计算策略并用Context类执行。代理模式则为对象提供代理以控制访问,常用于延迟加载或权限控制。如创建RealSubject和Proxy类,Proxy在调用RealSubject方法前可执行额外操作。这两种模式在复杂业务逻辑中发挥重要作用,根据需求选择合适模式解决问题。
|
1天前
|
设计模式 Java
【JAVA基础篇教学】第十四篇:Java中设计模式
【JAVA基础篇教学】第十四篇:Java中设计模式
|
1天前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
18 0
|
1天前
|
设计模式 前端开发 Java
19:Web开发模式与MVC设计模式-Java Web
19:Web开发模式与MVC设计模式-Java Web
24 4
|
1天前
|
设计模式 存储 前端开发
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
26 4
|
1天前
|
设计模式 缓存 监控
JAVA设计模式之结构型模式
结构模型:适配器模型、桥接模型、过滤器模型、组合模型、装饰器模型、外观模型、享受元模型和代理模型。
22 3
|
1天前
|
设计模式 算法 Java
Java基础教程(19)-设计模式简述
【4月更文挑战第19天】设计模式是软件设计中反复使用的代码设计经验,旨在提升代码的可重用性、可扩展性和可维护性。23种模式分为创建型、结构型和行为型三类。创建型模式如工厂方法、抽象工厂、建造者、原型和单例,关注对象创建与使用的分离。结构型模式涉及对象组合,如适配器、装饰器、外观等,增强结构灵活性。行为型模式专注于对象间职责分配和算法合作,包括责任链、命令、观察者等。设计模式提供标准化解决方案,促进代码交流和复用。
|
1天前
|
设计模式 Java
Java 设计模式:混合、装饰器与组合的编程实践
【4月更文挑战第27天】在面向对象编程中,混合(Mixins)、装饰器(Decorators)和组合(Composition)是三种强大的设计模式,用于增强和扩展类的功能。
21 1

热门文章

最新文章

http://www.vxiaotou.com