代理模式 (Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。

一、代理模式的形式

1.远程代理:为远程对象提供本地代表
2.虚拟代理:根据需要创建开销很大的对象
3.保护代理:控制对原始对象的访问权限
4.智能引用代理:在访问对象时执行附加操作

二、基本实现示例

1. 接口定义

// 主题接口
public interface ISubject
{
    void Request();
}

2. 真实主题类

// 真实主题类
public class RealSubject : ISubject
{
    public void Request()
    {
        Console.WriteLine("RealSubject: 处理请求");
    }
}

3. 代理类

// 代理类
public class Proxy : ISubject
{
    private RealSubject _realSubject;

    public void Request()
    {
        // 在调用真实对象方法前后可以添加额外逻辑
        if (_realSubject ==)
        {
            _realSubject = new RealSubject();
        }
        
        Console.WriteLine("Proxy: 在调用真实对象前");
        _realSubject.Request();
        Console.WriteLine("Proxy: 在调用真实对象后");
    }
}

4. 客户端使用

class Program
{
    static void Main(string[] args)
    {
        Proxy proxy = new Proxy();
        proxy.Request();
    }
}

三、实际应用示例

1、虚拟代理示例 - 图片加载代理

// 图片接口
public interface IImage
{
    void Display();
}

// 真实图片类(加载可能很耗时)
public class RealImage : IImage
{
    private string _filename;

    public RealImage(string filename)
    {
        _filename = filename;
        LoadFromDisk();
    }

    private void LoadFromDisk()
    {
        Console.WriteLine($"加载图片: {_filename}");
        // 模拟耗时操作
        Thread.Sleep(2000);
    }

    public void Display()
    {
        Console.WriteLine($"显示图片: {_filename}");
    }
}

// 图片代理(虚拟代理)
public class ImageProxy : IImage
{
    private string _filename;
    private RealImage _realImage;

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

    public void Display()
    {
        if (_realImage ==)
        {
            _realImage = new RealImage(_filename);
        }
        _realImage.Display();
    }
}

// 使用
class Program
{
    static void Main()
    {
        IImage image = new ImageProxy("test.jpg");
        
        // 第一次调用会实际加载图片
        Console.WriteLine("第一次调用:");
        image.Display();
        
        // 第二次调用直接使用已加载的图片
        Console.WriteLine("\n第二次调用:");
        image.Display();
    }
}

2.保护代理示例 - 权限控制

// 文档接口
public interface IDocument
{
    void Display();
    void Edit();
}

// 真实文档
public class RealDocument : IDocument
{
    private string _content;

    public RealDocument(string content)
    {
        _content = content;
    }

    public void Display()
    {
        Console.WriteLine($"显示文档内容: {_content}");
    }

    public void Edit()
    {
        Console.WriteLine("编辑文档...");
    }
}

// 文档代理(保护代理)
public class DocumentProxy : IDocument
{
    private RealDocument _document;
    private string _userRole;

    public DocumentProxy(string content, string userRole)
    {
        _document = new RealDocument(content);
        _userRole = userRole;
    }

    public void Display()
    {
        _document.Display();
    }

    public void Edit()
    {
        if (_userRole == "Admin")
        {
            _document.Edit();
        }
        else
        {
            Console.WriteLine("无权限编辑文档");
        }
    }
}

// 使用
class Program
{
    static void Main()
    {
        IDocument adminDoc = new DocumentProxy("机密文件", "Admin");
        IDocument userDoc = new DocumentProxy("普通文件", "User");
        
        Console.WriteLine("管理员尝试:");
        adminDoc.Display();
        adminDoc.Edit();
        
        Console.WriteLine("\n普通用户尝试:");
        userDoc.Display();
        userDoc.Edit();
    }
}

四、.NET 中的代理模式应用

  • WCF 服务代理:自动生成的客户端代理类
  • EF Core 延迟加载:通过代理实现延迟加载
  • 装饰器模式:常与代理模式结合使用
  • AOP 框架:如 Castle DynamicProxy

代理模式在需要控制资源访问、延迟加载或添加额外行为时非常有用,同时保持客户端代码的简洁性。

在这里插入图片描述

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐