代理设计模式
一、代理模式概述
代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(代理)来控制对另一个对象(目标对象)的访问。
代理模式的作用
- 控制访问:用于权限控制,例如用户权限验证。
- 延迟初始化:按需创建对象,优化资源使用。
- 日志记录:拦截方法调用,记录日志。
- 远程代理:用于分布式系统,如WCF、gRPC。
- 缓存代理:缓存数据库查询结果,提高性能。
代理模式的关键角色
- 抽象主题(Subject):定义代理和真实对象的公共接口。
- 真实主题(RealSubject):执行实际业务逻辑的类。
- 代理类(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,如日志、事务管理等,减少重复代码,提高可维护性。