代理模式(Proxy Pattern)

代理设计模式

一、代理模式概述

代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(代理)来控制对另一个对象(目标对象)的访问。

代理模式的作用

  • 控制访问:用于权限控制,例如用户权限验证。
  • 延迟初始化:按需创建对象,优化资源使用。
  • 日志记录:拦截方法调用,记录日志。
  • 远程代理:用于分布式系统,如WCF、gRPC。
  • 缓存代理:缓存数据库查询结果,提高性能。

代理模式的关键角色

  1. 抽象主题(Subject):定义代理和真实对象的公共接口。
  2. 真实主题(RealSubject):执行实际业务逻辑的类。
  3. 代理类(Proxy):持有真实对象的引用,并控制对其访问。

二、静态代理

实现静态代理

csharp 复制代码
using System;

// 1. 定义接口
public interface IService
{
    void Request();
}

// 2. 真实对象
public class RealService : IService
{
    public void Request()
    {
        Console.WriteLine("真实服务执行 Request 方法");
    }
}

// 3. 代理类
public class ServiceProxy : IService
{
    private readonly IService _realService;
    public ServiceProxy(IService realService)
    {
        _realService = realService;
    }
    public void Request()
    {
        Console.WriteLine("代理:执行前的操作");
        _realService.Request();
        Console.WriteLine("代理:执行后的操作");
    }
}

// 4. 客户端代码
public class Program
{
    public static void Main()
    {
        IService proxy = new ServiceProxy(new RealService());
        proxy.Request();
    }
}

优缺点

✅ 优点

  • 代码结构清晰,便于管理。
  • 适用于权限控制、日志等场景。

❌ 缺点

  • 需要手动编写代理类,代码量增加。
  • 代理类与真实类耦合度高。

三、动态代理

方式 1:使用 DispatchProxy

csharp 复制代码
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

public interface IService
{
    void Request();
}

public class RealService : IService
{
    public void Request()
    {
        Console.WriteLine("真实服务执行 Request 方法");
    }
}

public class ServiceProxy : DispatchProxy
{
    private IService _realService;
    public static IService Create(IService realService)
    {
        IService proxy = Create<IService, ServiceProxy>();
        ((ServiceProxy)proxy)._realService = realService;
        return proxy;
    }
    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        Console.WriteLine("动态代理:执行前的操作");
        object result = targetMethod.Invoke(_realService, args);
        Console.WriteLine("动态代理:执行后的操作");
        return result;
    }
}

public class Program
{
    public static void Main()
    {
        IService proxy = ServiceProxy.Create(new RealService());
        proxy.Request();
    }
}

方式 2:使用 Castle.DynamicProxy

csharp 复制代码
using System;
using Castle.DynamicProxy;

public interface IService
{
    void Request();
}

public class RealService : IService
{
    public void Request()
    {
        Console.WriteLine("真实服务执行 Request 方法");
    }
}

public class ServiceInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("动态代理:执行前的操作");
        invocation.Proceed();
        Console.WriteLine("动态代理:执行后的操作");
    }
}

public class Program
{
    public static void Main()
    {
        ProxyGenerator generator = new ProxyGenerator();
        IService proxy = generator.CreateInterfaceProxyWithTarget<IService>(new RealService(), new ServiceInterceptor());
        proxy.Request();
    }
}

四、静态代理 vs. 动态代理

特性 静态代理 动态代理
代码量 需要手写代理类 代码复用高
灵活性 低,需手动编写代理 高,代理类可动态生成
性能开销 低 运行时反射有一定开销
适用场景 日志、权限控制 AOP、远程调用

五、总结

  • 静态代理 适用于少量代理对象,代码清晰但不够灵活。
  • 动态代理 适用于需要大量代理、AOP编程,灵活但需要额外的运行时开销。
  • 选择哪种方式,取决于具体的需求和性能考虑。

推荐使用动态代理实现AOP,如日志、事务管理等,减少重复代码,提高可维护性。

相关推荐
samble2 小时前
从零搭建灌装监控系统(十九):单元测试实战,xUnit + 内存SQLite + 反射测试私有方法
c#·wpf·mvvm·modbus·工业控制
希洛兔2 小时前
状态模式详解:让对象随内部状态自动改变行为
java·设计模式·状态模式
人道领域5 小时前
【面试八股速通篇01】锁与并发工具
java·开发语言·面试·c#
宇卿.5 小时前
C#字段、属性、索引器、常量
开发语言·计算机视觉·c#
程序员Linc5 小时前
ONNXOCRSharp 开源手记 02|v0.4.0 PDF识别
开发语言·pdf·c#·ocr·onnxocrsharp
博风5 小时前
7、设计模式应用举例:策略模式:加密、解密文件
设计模式·策略模式
慧都小妮子6 小时前
MSG 附件太占内存?Aspose.Email for .NET 26.9 延迟加载
c#·.net·aspose·内存优化·延迟加载·aspose.email·附件内存
4SAPI6 小时前
Provider Adapter设计模式:如何让AI应用支持多个模型
网络·人工智能·设计模式
慧都小妮子6 小时前
FastReport PDF/UA 导出:让出海 PDF 满足无障碍合规要求
pdf·c#·fastreport·报表导出·pdf/ua·pdf 无障碍
geovindu8 小时前
rust: pool Pattern
开发语言·后端·设计模式·rust·对象池简写模式