设计模式 12 代理模式

设计模式 12

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • [设计模式 12](#设计模式 12)
    • [代理模式(Proxy Pattern)](#代理模式(Proxy Pattern))
      • [1 定义](#1 定义)
      • [2 结构](#2 结构)
      • [3 示例代码](#3 示例代码)
      • [4 特点](#4 特点)
      • [5 适用场景](#5 适用场景)
      • [6 与其他模式的关系](#6 与其他模式的关系)

代理模式(Proxy Pattern)

1 定义

代理模式通过创建一个代理对象来控制对另一个对象的访问。代理对象具有与原对象相同的接口,客户端可以通过代理对象访问实际的服务对象。代理对象可以在不影响客户端的情况下,对请求进行预处理或后处理。

2 结构

代理模式的结构包含以下角色:

  • Subject(抽象主题): 定义了代理类和真实类的公共接口。
  • RealSubject(真实主题): 实现了抽象主题的接口,是代理所代表的真实对象。
  • Proxy(代理): 实现了抽象主题接口,并持有一个真实主题对象的引用。代理对象可以在调用真实对象的操作前后执行一些操作。

UML 类图

scss 复制代码
+-----------------+
|   Subject       | <--------- 抽象主题
+-----------------+                 |
| + Request()     |                 |
+-----------------+                 |
        ^                           |
        |                           |
+-----------------+         +-----------------+
|   Proxy         |         |  RealSubject    |
+-----------------+         +-----------------+
| - realSubject:  | ------- | + Request()     |
|   RealSubject   |         +-----------------+
| + Request()     |
+-----------------+

3 示例代码

假设我们有一个需要访问的图像文件对象。图像文件可能很大,所以我们希望在图像真正需要显示时才加载它。在这种情况下,我们可以使用代理模式。

抽象主题接口

csharp 复制代码
// 抽象主题
public interface IImage
{
    void Display();
}

真实主题类

csharp 复制代码
// 真实主题类:真实的图像文件
public class RealImage : IImage
{
    private readonly string _filename;

    public RealImage(string filename)
    {
        _filename = filename;
        LoadImageFromDisk();  // 模拟加载图像文件
    }

    private void LoadImageFromDisk()
    {
        Console.WriteLine($"Loading image from disk: {_filename}");
    }

    public void Display()
    {
        Console.WriteLine($"Displaying image: {_filename}");
    }
}

代理类

csharp 复制代码
// 代理类:代理图像
public class ProxyImage : IImage
{
    private RealImage _realImage;
    private readonly string _filename;

    public ProxyImage(string filename)
    {
        _filename = filename;
    }

    public void Display()
    {
        if (_realImage == null)
        {
            _realImage = new RealImage(_filename);  // 延迟加载
        }
        _realImage.Display();
    }
}

客户端代码

csharp 复制代码
class Program
{
    static void Main(string[] args)
    {
        IImage image = new ProxyImage("test_image.jpg");

        // 图像第一次显示时,代理对象会加载真实图像
        image.Display();

        // 图像再次显示时,不需要再次加载
        image.Display();
    }
}

在这个例子中:

  • 抽象主题 IImage : 定义了 Display() 方法,所有图像对象都必须实现这个方法。
  • 真实主题类 RealImage : 实现了 IImage 接口,并在构造函数中模拟加载图像文件。Display() 方法显示图像。
  • 代理类 ProxyImage : 同样实现了 IImage 接口,持有一个 RealImage 对象的引用。只有在需要时,才会加载真实的图像文件,执行延迟加载。

运行结果

运行上述代码,你会看到以下输出:

plaintext 复制代码
Loading image from disk: test_image.jpg
Displaying image: test_image.jpg
Displaying image: test_image.jpg

在这个例子中,图像在第一次调用 Display() 时才会加载,之后的调用直接显示图像,无需再次加载。这就是代理模式的延迟加载(Lazy Loading)应用。

4 特点

  • 优点:

    • 控制对象访问: 可以在不影响客户端的情况下控制对目标对象的访问。

    • 延迟加载: 通过代理可以实现对象的延迟初始化,节省资源。

    • 权限控制: 可以通过代理实现对敏感对象的访问控制。

  • 缺点:

    • 增加复杂性: 增加了类的数量和系统的复杂性。

    • 可能引入性能开销: 代理模式可能会引入额外的处理逻辑,导致性能开销。

5 适用场景

  • 需要延迟加载的场景: 当对象的创建成本较高且不经常使用时。
  • 远程对象访问: 通过网络访问远程对象时,可以使用代理来隐藏复杂性。
  • 控制访问权限: 需要对对象的访问进行权限控制时。
  • 智能引用代理: 在访问对象时附加一些额外操作,如引用计数、日志记录等。

6 与其他模式的关系

  • 装饰器模式: 代理和装饰器都通过代理控制对象,但装饰器用于添加行为,而代理用于控制访问。
  • 适配器模式: 适配器模式改变接口以适配另一系统,而代理模式不改变接口,只是控制访问。

代理模式在设计复杂系统时提供了非常灵活的对象管理方式,通过合理使用代理,可以有效地提升系统的性能和安全性。

相关推荐
shinelord明24 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
大圣数据星球6 小时前
Fluss 写入数据湖实战
大数据·设计模式·flink
思忖小下7 小时前
梳理你的思路(从OOP到架构设计)_设计模式Template Method模式
设计模式·模板方法模式·eit
思忖小下17 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
biubiubiu070617 小时前
代理模式(JDK,CGLIB动态代理,AOP切面编程)
代理模式
liyinuo201719 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
aaasssdddd9621 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
T1an-121 小时前
设计模式之【观察者模式】
观察者模式·设计模式
思忖小下1 天前
梳理你的思路(从OOP到架构设计)_设计模式Factory Method模式
设计模式·工厂方法模式·eit
霁月风1 天前
设计模式——工厂方法模式
c++·设计模式·工厂方法模式