这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
- ?欢迎点赞 :? 收藏 ⭐留言 ? 如有错误敬请指正,赐人玫瑰,手留余香!
- ?本文作者:由webmote 原创,首发于 【掘金】
- ?作者格言: 生活在于折腾,当你不折腾生活时,生活就开始折腾你,让我们一起加油!???
? 01.代理模式
意图: 把用户无法访问的对象代理出去,使得你可以间接访问对象。
形象的说:就如同给你的浏览器增加加个代理,然后,你就可以翻越长江长城,直接看到外面的世界了。
友好提醒:vpn有罪!
问题领域: 跳过障碍,加点东东。
- 封装三方类库,并加点东东,
- 增加保护控制,
- 过滤请求,
- 为了资源、链接保护,封装原生类
- 产品仅提供接口,而非具体的类
解决方案: 我们使用UML图来描述它。
Proxy类有个BehindClass的实例成员,因此其可以直接访问BehindClass类中的所有公开方法,通过包装这些方法形成可被其他类调用的接口。
Client就是一个使用者,其内部可以实例化 Proxy类,并调用方法Request达到和调用 BehindClass的Request一样的效果,当然在Proxy类中,可以增加额外的权限安全判断,或引用计数等,以达到对BehindClass方法调用的控制。
效果:
- 好处:
- 隐藏BehindClass的直接调用;
- 开放对BehindClass的功能调用;
- 可以方便的增加权限、引用计数等相关的控制;
- 可以延迟加载重量级的资源;
- 限定:
- 如果BehindClass类接口众多,对Proxy来说,需要敲更多的类似代码。
? 02. dotnet core 源码赏析
在 aspnet Core
源代码内有一个动态客户端的代理`DynamicClientProxy,采用了代理模式。
internal class DynamicClientProxy : DynamicObject
{
private readonly IClientProxy _clientProxy;
public DynamicClientProxy(IClientProxy clientProxy)
{
_clientProxy = clientProxy;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object?[]? args, out object? result)
{
result = _clientProxy.SendCoreAsync(binder.Name, args!);
return true;
}
}
复制代码
代理模式超级简单吧,几乎不做什么事情,直接转发请求即可。
这里TryInvokeMember方法就是直接调用_clientProxy的SendCoreAsync方法完成对真实对象的方法调用代理。
? 03. dotnet 代理类实现
这是一个例子,我们来实现一个抽象工厂,接口定义如下:
internal class BehindResource{
public void PerformRWOperations()
{
Console.WriteLine("Performing Read Write operation on the Shared Folder");
}
}
class ResourceProxy
{
private BehindResource folder;
private Employee employee;
public ResourceProxy(Employee emp)
{
employee = emp;
}
public void PerformRWOperations()
{
if (employee.Role.ToUpper() == "CEO" || employee.Role.ToUpper() =="MANAGER")
{
folder = new BehindResource();
Console.WriteLine("Shared Folder Proxy makes call to the RealFolder 'PerformRWOperations method'");
folder.PerformRWOperations();
}
else
{
Console.WriteLine("Shared Folder proxy says 'You don't have permission to access this folder'");
}
}
}
复制代码
这里对能访问资源的雇员进行了限制,只有符合条件的雇员才可以访问到后台资源,其他雇员我们不允许它访问资源。
调用方,可以按照下列方式直接使用。
Console.WriteLine("Client passing employee with Role Developer to folderproxy");
Employee emp1 = new Employee("Anurag", "Anurag123", "Developer");
ResourceProxy proxy1 = new ResourceProxy(emp1);
proxy1.PerformRWOperations();
Console.WriteLine();
Console.WriteLine("Client passing employee with Role Manager to proxy");
复制代码
是的,通过上述的代理类,我们为后台资源增加了安全访问权限,对于客户端来说,它无法直接访问后后台资源,它只能通过我们提供的代理类访问后台资源,这样我们可以轻松控制资源了。
有类似需求的,均可以按照代理模式来解决。
? 04. 小结
如果我们有添加对现有对象的安全访问、简化复杂对象的 API、为远程资源提供接口、在不更改现有类代码的情况下向现有类添加线程安全功能等类似的业务设计时,可以考虑是否可以利用设计模式中的代码模式了。
例行小结,理性看待!
结的是啥啊,结的是我想你点赞而不可得的寂寞。???
?都看到这了,还在乎点个赞吗?
?都点赞了,还在乎一个收藏吗?
?都收藏了,还在乎一个评论吗?