java设计模式学习之【代理模式】

发布时间:2023年12月18日

引言

在现实生活中,我们经常使用代理来处理我们不想直接参与或无法直接参与的事务,例如,使用律师来代表法庭上的案件。在软件开发中,这种代理概念同样存在,被称为代理模式。代理模式允许我们通过创建一个替代对象(代理),来控制对其他对象的访问。这种模式在需要控制或增强对对象的访问时非常有用。

代理模式简介

定义与用途

代理模式(Proxy Pattern)是一种结构型设计模式,它通过提供一个替代对象(代理)来代表真实对象的操作。代理控制对原始对象的访问,可以在访问对象时添加一些附加操作,例如访问控制、延迟初始化、日志等。

实现方式

实现代理模式通常涉及以下几个关键组件:

  • 主题接口(Subject): 定义了代理和真实对象的共用接口,这样在任何使用真实对象的地方都可以使用代理。
  • 真实主题(Real Subject): 定义了代理所表示的真实对象。
  • 代理(Proxy): 维护一个对真实主题的引用,控制对真实主题的访问,并可以在访问前后添加额外的处理。

使用场景

代理模式适用于以下场景:

  • 当需要在不修改原始对象的情况下控制对对象的访问时。
  • 当需要为一个对象提供不同的访问控制层时,如为远程对象提供本地代表。
  • 当需要添加对象的创建和销毁的额外逻辑时,如实现延迟初始化。

例如:

  1. 远程代理(Remote Proxy):为远程对象(如网络服务)提供本地的代理对象。
  2. 虚拟代理(Virtual Proxy):用于延迟昂贵操作的对象的创建,直到真正需要该对象时。
  3. 保护代理(Protection Proxy):控制对原始对象的访问,适用于对象应有不同访问权限的场景。

优势与劣势

  • 优势
    分离任务:代理可以将复杂或耗时的工作从真实对象中分离出去。
    增加安全性:通过代理控制对真实对象的访问,增加安全层。
    扩展功能:在不改变真实对象代码的情况下增加额外功能。
  • 劣势
    增加代码复杂性:引入代理会增加系统的复杂性。
    可能会导致一些延迟:尤其是在远程代理的情况下。

在Spring框架中的应用

Spring框架广泛使用了代理模式,特别是在以下方面:

Spring AOP(面向切面编程):使用代理模式来实现方法拦截和增强,实现例如事务管理、安全检查等横切关注点。

事务管理:Spring通过代理模式管理事务,为方法调用提供声明式事务支持。

Spring Security:在安全框架中,代理用于在方法调用之前和之后执行安全检查。

图片加载示例

在这里插入图片描述
步骤 1:创建接口
首先定义了一个 Image 接口,用于展示图片。

public interface Image {
   void display();
}

步骤 2:实现具体类
创建了 RealImage 类,实现了 Image 接口。这个类代表实际加载的图片。

public class RealImage implements Image {

   private String fileName;

   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }

   @Override
   public void display() {
      System.out.println("展示 " + fileName);
   }

   private void loadFromDisk(String fileName){
      System.out.println("加载 " + fileName);
   }
}

创建了 ProxyImage 类,也实现了 Image 接口。这个类是 RealImage 对象的代理,负责在需要时加载图片。

public class ProxyImage implements Image {

   private RealImage realImage;
   private String fileName;

   public ProxyImage(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

步骤 3:使用代理对象
ProxyPatternDemo 类演示了如何使用 ProxyImage 来获取和展示 RealImage 对象。

public class ProxyPatternDemo {
	
   public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");

      // 图片将从磁盘加载
      image.display(); 
      System.out.println("");
      
      // 图片不会从磁盘重新加载
      image.display(); 	
   }
}

在这里插入图片描述

在这个示例中,ProxyImage 充当 RealImage 的代理。当第一次调用 display 方法时,ProxyImage 会创建一个 RealImage 对象并调用其 display 方法。当再次调用 display 方法时,由于 RealImage 对象已经创建,代理将直接使用已加载的对象,而不会再次从磁盘加载图片。

这种方式可以节约资源,特别是在处理大型资源(如大图片)时。通过使用代理模式,只有在实际需要时才加载资源,从而优化了性能并减少了内存占用。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

文章来源:https://blog.csdn.net/qq_33129875/article/details/134978400
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。