前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java设计模式(10)代理模式

Java设计模式(10)代理模式

作者头像
Jensen_97
发布2024-07-03 12:36:31
770
发布2024-07-03 12:36:31
举报
文章被收录于专栏:技术客栈

前言

在软件开发的世界里,设计模式如同一本精妙的编码诗集,已经成为一种标准的编程实践。在Java编程中,设计模式很重要。是软件开发中广泛应用的一种编程方法,它可以帮助开发人员更快地编写出高效、可靠和可维护的代码。本人将制作一个关于Java设计模式的系列文章,总共23种设计模式将以一篇一篇文章讲解,代码笔记已开源:Gitee点击跳转。在上一篇《Java设计模式(9)享元模式》文章中,我们介绍了享元模式。本文是这个系列的第十篇章,我们将讲解一下代理模式的实现方式、应用场景以及它的用途。

代理模式

代理模式中,一个类代表另一个类的功能,这种类型的设计模式属于结构型模式。代理模式通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介,负责将客户端的请求转发给目标对象,同时可以在转发请求前后进行额外的处理。

代理模式又有两种主要形式:

  • 静态代理:在编译时就已经确定了代理类和被代理类之间的关系,通常需要为每个被代理类都编写一个对应的代理类,并实现相同的接口。 静态代理的优点是简单易懂,缺点是不灵活,代码冗余。
  • 动态代理:在运行时动态生成代理对象,并根据反射机制调用被代理类的方法。 动态代理可以使用Java原生API或者第三方框架来实现,如JDK Proxy、CGLIB、等。

使用场景

  • 当需要在访问一个对象时进行一些控制或额外处理时,比如我想要在调用某个方法之前或之后添加日志、缓存、事务等功能。
  • 控制对原始对象的访问权限,常用于安全控制和权限管理。例如,实现一个文件访问权限控制时。

代码实现

以下将采用银行与代理银行之间的关系简单实现一下。

代码语言:javascript
复制
/**
 * 银行接口
 * @author Jensen
 * @date 2024-03-28
 * */
public interface Bank {
    void deposit(BigDecimal amount);
    void withdraw(BigDecimal amount);
}
/**
 * 实现银行接口
 * @author Jensen
 * @date 2024-03-28
 * */
public class RealBank implements Bank {
    private BigDecimal balance = new BigDecimal("0.00");

    @Override
    public void deposit(BigDecimal amount) {
        balance = balance.add(amount);
        System.out.println("存款操作完成。当前余额:" + balance + "元");
    }

    @Override
    public void withdraw(BigDecimal amount) {
        if (balance.compareTo(amount) >= 0) {
            balance = balance.subtract(amount);
            System.out.println("取款操作完成。当前余额:" + balance + "元");
        } else {
            System.out.println("余额不足。当前余额:" + balance + "元");
        }
    }
}

以上代码我们创建了一个Bank,分别有depositwithdraw,然后有RealBank实现了Bank并对两个方法做了实际处理。接下来我们需要创建代理对象去代理这个RealBank

静态代理

代码语言:javascript
复制
/**
 * 代理银行
 * @author Jensen
 * @date 2024-03-28
 * */
public class ProxyRealBank implements Bank {
    private final RealBank realBank;

    public ProxyRealBank() {
        this.realBank = new RealBank();
    }

    @Override
    public void deposit(BigDecimal amount) {
        realBank.deposit(amount);
    }

    @Override
    public void withdraw(BigDecimal amount) {
        realBank.withdraw(amount);
    }
}

ProxyRealBank 类也实现了 Bank 接口,但它不直接处理depositwithdraw,而是将请求转发给一个内部的 RealBank 对象。充当一个中介角色,并且也可以做一些额外的操作。外部只需要调用它就OK了。

动态代理

代码语言:javascript
复制
/**
 * 代理银行(动态代理)
 * @author Jensen
 * @date 2024-03-28
 * */
public class BankInvocationHandler implements InvocationHandler {
    private final Object obj;

    public BankInvocationHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(obj, args);
    }
}

上述代码使用JDK动态代理实现

  • BankInvocationHandler 类实现了 InvocationHandler 接口。这个接口有一个方法 invoke,用于处理对代理实例的方法调用。
  • BankInvocationHandler 的构造方法接受一个对象作为参数(可代理多种对象),这个对象就是实际处理方法调用的对象。在这里我们是 RealBank 类的实例。
  • invoke 方法会在代理实例上调用任何方法时被调用。它接受三个参数:proxy:代理实例、method:被调用的方法、args:方法调用的参数。在 invoke 方法中,实际的方法调用被转发给了 obj 对象(即本文中的 RealBank 类实例)。

测试使用

代码语言:javascript
复制
System.out.println("------------------------------代理模式(静态代理)-----------------------------");
Bank bank = new ProxyRealBank();
// 存款和取款
BigDecimal money1 = new BigDecimal("100.50");
BigDecimal money2 = new BigDecimal("53.20");
BigDecimal money3 = new BigDecimal("47.55");
System.out.println("向银行存款"+money1+"元");
bank.deposit(money1);
System.out.println("向银行取款"+money2+"元");
bank.withdraw(money2);
System.out.println("向银行取款"+money3+"元");
bank.withdraw(money3);
System.out.println("------------------------------代理模式(动态代理)-----------------------------");
RealBank realBank = new RealBank();
BankInvocationHandler handler = new BankInvocationHandler(realBank);
// 使用动态代理创建 Bank 接口的代理对象
Bank bank1 = (Bank) Proxy.newProxyInstance(Bank.class.getClassLoader(),new Class<?>[]{Bank.class},handler);
System.out.println("向银行存款"+money1+"元");
bank1.deposit(money1);
System.out.println("向银行取款"+money2+"元");
bank1.withdraw(money2);
System.out.println("向银行取款"+money3+"元");
bank1.withdraw(money3);

结语

代理模式 主要解决的是在直接访问某些对象时可能遇到的问题,例如对象创建成本高、需要安全控制或远程访问等。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024/07/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 代理模式
  • 使用场景
  • 代码实现
    • 静态代理
      • 动态代理
      • 测试使用
      • 结语
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档