我们回顾以下电子商务中常见的现象 =》代购,简单的说就是找人帮忙购买所需的商品,当然代购者可能需要向实施代购的人支付一定的费用。代购的两种情况:
代理模式是一种对象结构型模式。在代理模式中引人了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。
代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。
代理模式包含以下3个角色:
代理模式的结构图比较简单,但在实际的使用和实现过程中要复杂得多,特别是代理类的设计和实现。典型代码如下:
///
/// 抽象主题类
///
abstract class Subject
{
public abstract void Request();
}
///
/// 真实主题类
///
class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("实现具体的业务方法。");
}
}
///
/// 代理类
///
class Proxy : Subject
{
//维持一个对真实主题对象的引用
private readonly RealSubject realSubject = new RealSubject();
public void PreRequest()
{
Console.WriteLine("调用真实对象方法前的预处理业务。");
}
public override void Request()
{
PreRequest();
realSubject.Request();
PostRequest();
}
public void PostRequest()
{
Console.WriteLine("调用真实对象方法后的预处理业务。");
}
}
在实际开发中,代理类的实现要比上述的例子复杂得多;
代理模式的分类,根据其目的和实现方式的不同,代理模式可以分为以下几种:
在这些常用的代理模式中,有些代理类的设计非常复杂,例如远程代理类,它封装了底层网络通信和对远程对象的调用,其实现较为复杂。
某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下:
现使用代理模式设计并实现该收费商务信息查询系统。
using System;
namespace ProxyPattern.BusinessQuerySystem
{
///
/// 身份校验类,业务类,用于验证用户身份信息;
///
class AccessValidator
{
//模拟实现登录验证
public bool Validate(string userId)
{
Console.WriteLine($"在数据库中验证用户'{userId}'是否是合法用户?");
if (userId.Equals("杨过"))
{
Console.WriteLine("'{0}'登录成功!",userId);
return true;
}
else
{
Console.WriteLine("'{0}'登录失败!", userId);
return false;
}
}
}
}
using System;
namespace ProxyPattern.BusinessQuerySystem
{
class Logger
{
//模拟实现日志记录
public void Log(string userId)
{
Console.WriteLine($"更新数据库,用户'{userId}'查询次数加1!");
}
}
}
namespace ProxyPattern.BusinessQuerySystem
{
interface ISearcher
{
string DoSearch(string userId, string keyword);
}
}
using System;
namespace ProxyPattern.BusinessQuerySystem
{
class RealSearcher : ISearcher
{
//模拟查询商务信息
public string DoSearch(string userId, string keyword)
{
Console.WriteLine("用户'{0}'使用关键词'{1}'查询商务信息!",userId,keyword);
return "返回具体内容";
}
}
}
namespace ProxyPattern.BusinessQuerySystem
{
class ProxySearcher : ISearcher
{
private readonly RealSearcher searcher = new RealSearcher(); //维持一个对真实主题的引用
private AccessValidator validator;
private Logger logger;
public string DoSearch(string userId, string keyword)
{
//如果身份验证成功,则执行查询
if (this.Validate(userId))
{
string result = searcher.DoSearch(userId, keyword); //调用真实主题对象的查询方法
this.Log(userId); //记录查询日志
return result; //返回查询结果
}
else
{
return null;
}
}
//创建访问验证对象并调用其Validate()方法实现身份验证
public bool Validate(string userId)
{
validator = new AccessValidator();
return validator.Validate(userId);
}
//创建日志记录对象并调用其Log()方法实现日志记录
public void Log(string userId)
{
logger = new Logger();
logger.Log(userId);
}
}
}
完整代码示例请查看=》https://gitee.com/dolayout/DesignPatternOfCSharp/tree/master/DesignPatternOfCSharp/ProxyPattern
远程代理(Remote Proxv)是一种常用的代理模式,它使得客户端程序可以访问在远程主机上的对象,远程主机可能具有更好的计算性能与外理速度,可以快速地响应并处理客户端的请求。远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户端完全可以认为被代理的远程业务对象是在本地而不是在远程,而远程代理对象承担了大部分的网络通信工作,并负责对远程业务方法的调用。
客户端对象不能直接访问远程主机中的业务对象,只能采取间接访问的方式。远程业务对象在本地主机中有一个代理对象,该代理对象负责对远程业务对象的访问和网络通信,它对于客户端对象而言是透明的。客户端无须关心实现具体业务的是谁,只需要按照服务接口所定义的方式直接与本地主机中的代理对象交互即可。
在基于.NET平台的分布式技术,例如 DCOM(Distribute Component Object Model分布式组件对象模型)、Web Service 中,都应用了远程代理模式,感兴趣的小伙伴可以自行查阅相关资料行扩展学习。
虚拟代理(Virtual Proxy)也是一种常用的代理模式,对于一些占用系统资源较多或者加载时间较长的对象,可以给这些对象提供一个虚拟代理。在真实对象的创建成功之前虚拟代理扮演真实对象的替身,而当真实对象创建之后,虚拟代理将用户的请求转发给真实对象。
通常,在以下两种情况下可以考虑使用虚拟代理:
无论是以上哪种情况,虚拟代理都是用一个“虚假”的代理对象来代表真实对象,通过代理对象来间接引用真实对象,可以在一定程度上提高系统的性能。
缓冲代理(Cache Proxy)也是一种较 为常用的代理模式,它为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,从而避免某些方法的重复执行,优化系统性能。
在微软示例项目 PetShop 4.0 的业务逻辑层(Business Logic Layer,BLL)中定义了 Product、Category、Item 等类,它们封装了相关的业务方法,用于调用数据访问层(DataAccess Layer, DAL)对象访问数据库,以获取相关数据。为了改进系统性能,PetShop 4. 0为这些实现方法增加了缓存机制,引人一个新的对象去控制原来的BLL业务逻辑对象,这些新的对象对应于代理模式中的代理对象。在引入代理模式后,实现了在缓存级别上对业务对象的封装,增强了对业务对象的控制,如果需要访问的数据在缓存中已经存在,则无须再重复执行获取数据的方法,直接返回存储在缓存中的数据即可。由于原有业务对象(真实对象)和新增代理对象暴露在外的方法是一致的,因而对于调用方(即客户端)而言,调用代理对象与真实对象并没有实质的区别。
这些新引人的代理类包括 ProductDataProxy、CategoryDataProxy 和 ItemDataProxy 等。下面以 PetShop.BLL.Product 业务对象为例进行说明,PetShop 4.0 为其建立了代理对象 ProductDataProxy ,并在该代理对象的 GetProductsByCategory() 方法,同时增加了缓存机制,如下入所示:
在 ProductDataProxy 类中存在以下代码片段:
PetShop vNext 访问地址 =》https://archive.codeplex.com/?p=petshopvnext#DownloadId=25356
CodePlex 是微软的免费开源项目托管网站,趁着在退役前(2021年7月1日)网站还能访问(目前处于存档模式),页面截图做个历史 (* ̄︶ ̄)
petshopvnext 源代码地址 =》https://download.csdn.net/download/ChaITSimpleLove/16686855
Microsoft .NET PetShop 相关参考文章:
代理模式是常用的结构型设计模式之一,它为对象的间接访问提供了一个解决方案,可以对刘象的访问进行控制。代理模式的类型较多,其中远程代理、虚拟代理、保护代理等在软件开发中的应用非常广泛。
此外,不同类型的代理模式具有独特的优点,例如:
代理模式的类型较多,不同类型的代理模式有不同的优缺点,它们应用于不同的环境;