代理模式 Proxy
Intro
代理模式,给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
比如生活中常见的中介,VPN,网络代理等
利用代理模式,我们可以对实际的操作做一些额外的逻辑,比如加一些异常捕捉,缓存,日志记录或者耗时统计等等,基于动态代理的 AOP 模式也是代理模式的实际应用。
Prototype
public abstract class Subject
{
public abstract void Request();
}
public class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("request from real subject");
}
}
public class Proxy0 : Subject
{
private Subject _subject;
public override void Request()
{
if (null == _subject)
{
_subject = new RealSubject();
}
_subject.Request();
}
}
public class Proxy : Subject
{
private readonly Subject _subject;
public Proxy(Subject subject) => _subject = subject;
public override void Request()
{
_subject.Request();
}
}
应用场景
业务系统的非功能性需求开发
代理模式最常用的一个应用场景就是,在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。
代理模式在 RPC 中的应用
RPC 框架也可以看作一种代理模式,客户端在使用 RPC 服务的时候,就像使用本地函数一样,无需了解跟服务器交互的细节。除此之外,RPC 服务的开发者也只需要开发业务逻辑,就像开发本地使用的函数一样,不需要关注跟客户端的交互细节。
AOP(面向切面编程)
我们可以基于动态代理来实现一个 AOP 框架,这也是目前 AOP 框架中主流的实现方式,在 .NET 里通常会使用 Emit 动态生成代理类型。
结合 AOP 我们很多非业务功能可以变得很容易实现,比如上面提到的日志、统计,鉴权,事务等,可以让我们更加聚焦于核心业务的实现。
More
代理模式和前面我们提到的装饰模式有些像,他们都可以在不修改原始类的情况下增加新的功能,但是他们是有区别的,代理更多的是强调对对象的访问控制,而装饰更多的在于新增功能,代理通常只有一层代理,而装饰模式可以有很多装饰器,支持多个装饰器的嵌套使用,而且代理模式实际使用的代理对象,而装饰模式实际使用的还是原来的对象只是通过装饰器模式增加了额外功能。
有很多 Wrapper
也是代理模式的实现,通常很多开源项目里的 Proxy
/Wrapper
大多数都是代理模式的应用