设计模式-06.代理模式(Proxy Pattern)-静态代理
发布日期:2021-05-20 05:12:29 浏览次数:19 分类:精选文章

本文共 3057 字,大约阅读时间需要 10 分钟。

代理模式(Proxy Pattern)

在计算机科学中,设计模式是一个非常重要的概念,用于解决常见的问题和提高代码的可维护性和扩展性。今天,我们将深入探讨代理模式(Proxy Pattern),这是一个常用的结构型模式。通过理解它的定义、实现方法以及应用场景,我们可以更好地掌握这一模式在实际开发中的应用。


定义与目的

代理模式的核心思想是一个对象通过另一个对象代表自己,控制对这个对象的访问。这种模式适用于以下情况:

  • 远程访问:当目标对象位于远程服务器时,直接连接可能会带来性能问题。通过使用代理,可以在本地创建一个中间对象来处理调用。
  • 安全控制:对于需要安全访问的目标对象,代理模式能够控制访问权限,确保只有经过授权的用户或操作才能直接访问目标对象。
  • 资源管理:当目标对象的创建或销毁产生昂贵的开销时(例如,资源有限的环境中),代理模式可以帮助优化资源使用。

目标对象代理对象之间,代理对象会控制对目标对象的访问行为,并对目标对象进行一些额外的操作或转换。


静态代理与动态代理

在代理模式中,实现方式分为静态代理动态代理两种:

  • 静态代理:在开发阶段就预先定义代理类,并与目标对象一起使用。这种方式实现简单,但可能会限制灵活性,因为代理类必须预先编写完成。

  • 动态代理:在运行时动态生成代理类。这种方式更加灵活,能够在目标对象的接口定义的基础上,动态地创建符合接口要求的代理实现。常见的动态代理实现方式是基于Java中的ReflectAPI或使用Spring AOP的缓存。


  • 实现步骤

    以下是一个典型的代理模式实现步骤:

  • 定义接口:首先,我们需要定义一个接口(这种情况下,称为服务接口business interface),这个接口定义了目标对象需要的所有方法。

  • 创建目标类:实现上述接口的具体类,称为目标类真实类(Real Class)。这个类通常负责核心的业务逻辑。

  • 创建代理类:创建一个类来实现接口。这个类将称为代理类(Proxy Class),其内部持有一个目标对象的引用。通过代理类,你可以与目标对象进行交互,而无需直接访问目标对象。

  • 创建动态代理代理(可选):如果采用动态代理模型,可以利用反射机制或特定的框架(例如,Spring框架的AOP机制)来生成代理类,这样可以实现接口的部分方法或全部方法的动态代理。


  • 代码示例

    让我们用一个简单的图片加载示例来理解代理模式。

  • 定义接口

    public interface Image {    void display();}
  • 目标类(RealImage):

    public class RealImage implements Image {    private String fileName;    public RealImage(String fileName) {        this.fileName = fileName;        loadFromDisk(fileName);    }    public void display() {        System.out.println("显示图片:" + fileName);    }    private void loadFromDisk(String fileName) {        System.out.println("从磁盘加载图片:" + fileName);    }}
  • 静态代理类(ProxyImage):

    public class ProxyImage implements Image {    private Image realImage;    private String fileName;    public ProxyImage(String fileName) {        this.fileName = fileName;    }    public void display() {        if (realImage == null) {            realImage = new RealImage(fileName);        }        realImage.display();    }}
  • 测试类(ProxyPatternDemo):

    public class ProxyPatternDemo {    public static void main(String[] args) {        Image image = new ProxyImage("test_10mb.jpg");        System.out.println("第一次显示图片,会加载到磁盘:");        image.display();        System.out.println("");        System.out.println("第二次显示图片,不会重新加载:");        image.display();    }}
  • 运行代码时,输出结果将如下:

    从磁盘加载图片:test_10mb.jpg显示图片:test_10mb.jpg显示图片:test_10mb.jpg

    优缺点分析

    优点

  • 简化访问:通过引入代理层,可以一次性控制对目标对象的访问。
  • 资源优化:在某些情况下,代理模式能够显著减少资源的占用(例如,延迟加载)。
  • 安全性:适用于需要安全访问控制的情境,例如加密通信。
  • 扩展性:通过动态代理模式,可以轻松添加新的功能,例如日志记录或异常处理。
  • 缺点

  • 性能问题:在频繁的调用场景下,引入代理层可能导致性能下降。
  • 代码复杂度:动态代理模式通常需要额外的依赖(如反射API或框架),增加了代码的复杂度。
  • 设计难度:当目标对象的接口频繁变动时,维护代理代码可能会变得困难。

  • 使用场景

  • 远程代理:当目标对象位于远程服务器时,使用代理启动本地服务,以减少网络延迟和带宽消耗。

  • 虚拟代理:当目标对象尚未创建时,使用虚拟代理立即返回操作结果(如文件或资源的占位符)。

  • Copy-on-Write代理:在资源分割或共享环境中,保证线程安全地对资源进行操作。

  • 保护代理:限制对目标对象的直接访问,只允许经过特定校验的方法调用。

  • 缓存代理:缓存频繁访问的数据,减少后端服务器的负载。

  • 防火墙代理:在防火墙环境中,动态代理接口以转发请求,而不直接暴露目标对象。

  • 同步化代理:确保_singleton HOLDER只允许单例访问。

  • 智能引用代理:延迟加载对象,确保对象在使用前被初始化。


  • 注意事项

  • 适配器模式与代理模式的区别

    • 适配器模式:将一类的接口适配到另一类,以支持不兼容的接口。
    • 代理模式:创建一个与目标类具有相同接口的新对象,以控制访问。
  • 装饰器模式与代理模式的区别

    • 装饰器模式:在已有对象上增加功能,通过组合对象的方式增强功能。
    • 代理模式:间接控制对目标对象的访问。

  • 总结

    代理模式是一种强大的设计模式,适用于在不直接访问目标对象的情况下控制其行为。通过引入一个中间层(代理类),它可以在程序运行过程中对目标对象进行资源管理或行为控制。静态代理和动态代理分别在开发阶段和运行阶段实现对目标对象的代理规则。如果需要更多练习,我建议您通过实际项目来应用这一模式,并对比不同情况下的优缺点。通过不断实践,您会对其内在机制和应用场景有更深入的理解。

    上一篇:设计模式-05.建造者模式(Builder Pattern)
    下一篇:设计模式-04.模板方法模式

    发表评论

    最新留言

    留言是一种美德,欢迎回访!
    [***.207.175.100]2025年04月18日 01时37分30秒