设计模式 2 代理模式-静态或者动态

本文详细介绍了代理模式的概念,通过房东、中介和买卖房子的例子阐述了代理模式的用途。接着讲解了静态代理,包括其原理、优点、缺点及代码实现,展示了如何通过代理对象对目标对象的功能进行扩展。然后介绍了动态代理,说明了其工作原理,通过InvocationHandler接口实现方法的动态调用,并给出了动态代理的代码示例。文章最后提供了静态代理和动态代理的对比,帮助理解两种代理模式的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 代理模式

1.1 代理模式

在不修改目标对象代码的前提下,通过代理对象调用目标对象的方法,并在调用前后实现一些增强性的业务逻辑。例子如下:

以房东,中介,买卖房子为例子,说明什么是代理,说白就是房东卖房子因为一些利益,或者怕麻烦,没有经商头脑等各种原因,不能和客户直接进行接触买卖房子,这时候需要中介代理其进行卖房子。

1.2 代理优点

优点一:可以隐藏委托类(房东)的实现;
优点二:可以实现客户与委托类(房东)间的解耦,在不修改委托类(房东)代码的情况下能够做一些额外的处理。

在不修改目标类的情况下可以实现一些额外处理。

1.3 代理角色说明

目标类,委托类,被代理类 均是一个东西。

代理类:目前只有一个叫法

二  静态代理

2.2  静态代理原理

(投诉12315,就能整治无量商家)

目标类和代理类实现了相同的接口,在代理类中依赖了目标类,代理类的方法中调用了目标类的方法,并做了一些增强性的工作。

2.3  静态代理优缺点

优点:在不修改目标对象的功能前提下,能通过代理对象对目标对象的功能进行扩展和增强。
 
缺点: 
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。 
一旦接口增加方法,目标对象与代理对象都要维护。
https://www.cnblogs.com/karrya/p/16694251.html
https://blog.youkuaiyun.com/hc1285653662/article/details/127199791

2.4  静态代理代码实现

1.创建一个接口(MaiFang),定义目标类要实现方法(sellHouse)

2.创建一个目标类(FangDong),并实现此接口(MaiFang),重写接口方法(sellHouse)。

3.创建一个代理类(ZhongJie),并实现此接口(MaiFang),重写接口方法(sellHouse)。同时通过代理类的构造函数实例化目标类对象, 在代理类的方法中调用目标类对象方法的前后实现业务增强的代码。

4.实例化一个代理类对象和目标类对象,并将目标类对象作为参数,传入代理对象的实例中,通过代理对象调用自己的方法,从而实现调用目标类(因为在代理类的方法调用了目标类的方法,同时实现了一些业务增强)的方法。

2.4.1 创建一个卖房接口

public interface MaiFang {
    public void sellHouse();
}

2.4.2 创建一个卖房实现类(房东)

public class FangDong  implements MaiFang{
 private  int money;

    public FangDong(int money) {
        this.money = money;
    }

    @Override
    public void sellHouse() {
        System.out.println("我是房东,此房卖"+money+"元");
    }
}

2.4.3 创建一个代理类(中介)

public class ZhongJie implements MaiFang{
    private FangDong fd;

    public ZhongJie(FangDong fd) {
        this.fd = fd;
    }

    @Override
    public void sellHouse() {
        System.out.println("我是中介,卖房之前进行售前处理。。。。");
        fd.sellHouse();
        System.out.println("我是中介,卖房之后进行售后处理。。。。");
    }
}

2.1.4 创建一个客户端

 二者前后比较之后,可以看到,在代理类中调用目标类,且可以在调用目标类前后,可以实现增强性功能。(投诉12315,就能整治无量商家)

public class TestDy {
    public static void main(String[] args) {
        //不使用代理的话
        System.out.println("===============不使用代理之前调用:");
        FangDong fangDong=new FangDong(50);
        fangDong.sellHouse();
        System.out.println("===============使用代理后:");
        //使用代理
        FangDong fangDong1=new FangDong(40);
        ZhongJie zhongJie=new ZhongJie(fangDong1);
        zhongJie.sellHouse();
       }
}

结果如下: 

三  动态代理

3.1 动态代理

动态代理: 在程序的执行过程中,使用jdk的反射机制,创建代理对象,并动态的指定代理的目标类,并调用目标类方法的同时,实现一些增强性业务逻辑。
动态代理的实现方式常用有两种:
- 使用JDK代理
- 通过CDLIB代理
jdk动态代理是基于Java的反射机制实现的,使用jdk反射包下的Proxy和InvocationHandler实现代理对象的动态创建。

3.2 InvocationHandler接口

3.定义一个调用处理器类,这个类必须实现InvocationHandler接口,在这个实现类中就是要调用代理对象。调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。

 3.3 动态代理逻辑

1.创建一个接口,定义目标类要实现的方法

2.定义一个目标类,实现此接口,并重写接口中的方法
3.定义InvocationHandler接口的实现类(调用处理器类),调用invoke()方法,并完成对目标对象的业务增强
4.实例化目标类对象,并作为参数传入代理器对象中,通过proxy的newProxyInstance方法生成代理对象,将返回结果的值转成接口类型
5.通过代理对象调用代理的方法,代理方法中会去调用目标类的方法并实现一些业务增强。

3.1.1 创建一个卖房接口

public interface Seller {
    public void  sellHouse();
}

3.1.2 创建一个卖房实现类(房东)

package com.ljf.netty.proxy;

/**
 * @ClassName: FangDong
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2022/07/17 12:51:07
 * @Version: V1.0
 **/
public class FangDong implements Seller {
    private int money;
    public FangDong(int money) {
        this.money=money;
    }
    @Override
    public void sellHouse() {
        System.out.println("我是房东,我卖的房子为:"+money+" 万!!!");
    }
}

3.1.3 创建一个调用处理器类,这个类必须实现InvocationHandler接口,作为调用处理器,”拦截“对代理类方法的调用

package com.ljf.netty.proxy.dong;

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

/**
 * @ClassName: ZhongjieDynamicProxy
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2022/07/17 15:36:15
 * @Version: V1.0
 **/
public class ZhongjieDynamicProxy implements InvocationHandler {
    private Object obj; //obj为委托类对象;
    public ZhongjieDynamicProxy(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是中介,我在准备售前的事情");
        Object result = method.invoke(obj, args);
        System.out.println("我是中介,我在准备售后的事情=======");
        return result;
    }
}

3.1.4 创建客户端

package com.ljf.netty.proxy.dong;

import com.ljf.netty.proxy.FangDong;
import com.ljf.netty.proxy.Seller;

import java.lang.reflect.Proxy;

/**
 * @ClassName: TestDynamic
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2022/07/17 16:05:47
 * @Version: V1.0
 **/
public class TestDynamic {
    public static void main(String[] args) {
        //创建委托,被代理对象(房东)
        FangDong s=new FangDong(50);
        //创建调用处理器对象, 处理所有的代理对象上的方法调用
        ZhongjieDynamicProxy zdp=new ZhongjieDynamicProxy(s);
        //创建一个代理对象,(中介)
        Seller se=(Seller) (Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), zdp));
       //调用代理的方法
        se.sellHouse();
    }
}

 https://www.jb51.net/article/86531.htm

Java动态代理 - 简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值