C#设计模式之代理模式(三)
15.4 远程代理
远程代理(Remote Proxy)是一种常用的代理模式,它使得客户端程序可以访问在远程主机上的对象,远程主机可能具有更好的计算性能与处理速度,可以快速响应并处理客户端的请求。远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户端完全可以认为被代理的远程业务对象是在本地而不是在远程,而远程代理对象承担了大部分的网络通信工作,并负责对远程业务方法的调用。
远程代理示意图如图15-5所示,客户端对象不能直接访问远程主机中的业务对象,只能采取间接访问的方式。远程业务对象在本地主机中有一个代理对象,该代理对象负责对远程业务对象的访问和网络通信,它对于客户端对象而言是透明的。客户端无须关心实现具体业务的是谁,只需要按照服务接口所定义的方式直接与本地主机中的代理对象交互即可。
图15-5 远程代理示意图
在基于.NET平台的分布式技术,例如DCOM(Distribute Component Object Model,分布式组件对象模型)、Web Service中,都应用了远程代理模式,大家可以查阅相关资料进行扩展学习。
15.5 虚拟代理
虚拟代理(Virtual Proxy)也是一种常用的代理模式,对于一些占用系统资源较多或者加载时间较长的对象,可以给这些对象提供一个虚拟代理。在真实对象创建成功之前虚拟代理扮演真实对象的替身,而当真实对象创建之后,虚拟代理将用户的请求转发给真实对象。
通常,在以下两种情况下可以考虑使用虚拟代理:
(1) 由于对象本身的复杂性或者网络等原因导致一个对象需要较长的加载时间,此时可以用一个加载时间相对较短的代理对象来代表真实对象。通常在实现时可以结合多线程技术,一个线程用于显示代理对象,其他线程用于加载真实对象。这种虚拟代理模式可以应用在程序启动的时候,由于创建代理对象在时间和处理复杂度上要少于创建真实对象,因此,在程序启动时,可以用代理对象代替真实对象初始化,大大加速了系统的启动时间。当需要使用真实对象时,再通过代理对象来引用,而此时真实对象可能已经成功加载完毕,可以缩短用户的等待时间。
(2) 当一个对象的加载十分耗费系统资源的时候,也非常适合使用虚拟代理。虚拟代理可以让那些占用大量内存或处理起来非常复杂的对象推迟到使用它们的时候才创建,而在此之前用一个相对来说占用资源较少的代理对象来代表真实对象,再通过代理对象来引用真实对象。为了节省内存,在第一次引用真实对象时再创建对象,并且该对象可被多次重用,在以后每次访问时需要检测所需对象是否已经被创建,因此在访问该对象时需要进行存在性检测,这需要消耗一定的系统时间,但是可以节省内存空间,这是一种用时间换取空间的做法。
无论是以上哪种情况,虚拟代理都是用一个“虚假”的代理对象来代表真实对象,通过代理对象来间接引用真实对象,可以在一定程度上提高系统的性能。
15.6 缓冲代理
缓冲代理(Cache Proxy)也是一种较为常用的代理模式,它为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,从而可以避免某些方法的重复执行,优化系统性能。
在微软示例项目PetShop 4.0的业务逻辑层(Business Logic Layer, BLL)中定义了Product、Category、Item等类,它们封装了相关的业务方法,用于调用数据访问层(Data Access Layer, DAL)对象访问数据库,以获取相关数据。为了改进系统性能,PetShop 4.0为这些实现方法增加缓存机制,引入一个新的对象去控制原来的BLL业务逻辑对象,这些新的对象对应于代理模式中的代理对象。在引入代理模式后,实现了在缓存级别上对业务对象的封装,增强了对业务对象的控制,如果需要访问的数据在缓存中已经存在,则无须再重复执行获取数据的方法,直接返回存储在缓存中的数据即可。由于原有业务对象(真实对象)和新增代理对象暴露在外的方法是一致的,因而对于调用方即客户端而言,调用代理对象与真实对象并没有实质的区别。
这些新引入的代理类包括ProductDataProxy、CategoryDataProxy和ItemDataProxy等。下面以PetShop.BLL.Product业务对象为例进行说明,PetShop 4.0为其建立了代理对象ProductDataProxy,并在ProductDataProxy的GetProductsByCategory()方法中调用了业务逻辑层Product类的GetProductsByCategory()方法,同时增加了缓存机制。如图15-6所示:
图15-6 PetShop4.0缓存代理示意图
在ProductDataProxy类中存在如下代码片段:
- public static class ProductDataProxy
- {
- private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings ["ProductCacheDuration"]);
- private static readonly bool enableCaching = bool.Parse(ConfigurationManager. AppSettings["EnableCaching"]);
- public static IList GetProductsByCategory(string category)
- {
- Product product = new Product();
- //如果缓存被禁用,则直接通过product对象来获取数据
- if (!enableCaching)
- {
- return product.GetProductsByCategory(category);
- }
- string key = "product_by_category_" + category;
- //从缓存中获取数据
- IList data = (IList )HttpRuntime.Cache[key];
- //如果缓存中没有数据则执行如下代码
- if (data == null)
- {
- data = product.GetProductsByCategory(category);
- //通过工厂创建AggregateCacheDependency对象
- AggregateCacheDependency cd = DependencyFacade.GetProductDependency ();
- //将数据存储在缓存中,并添加必要的AggregateCacheDependency对象
- HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(product Timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
- }
- return data;
- }
- ……
- }
public static class ProductDataProxy
{
private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings ["ProductCacheDuration"]);
private static readonly bool enableCaching = bool.Parse(ConfigurationManager. AppSettings["EnableCaching"]); public static IList GetProductsByCategory(string category)
{
Product product = new Product(); //如果缓存被禁用,则直接通过product对象来获取数据
if (!enableCaching)
{
return product.GetProductsByCategory(category);
} string key = "product_by_category_" + category;
//从缓存中获取数据
IList data = (IList )HttpRuntime.Cache[key]; //如果缓存中没有数据则执行如下代码
if (data == null)
{
data = product.GetProductsByCategory(category);
//通过工厂创建AggregateCacheDependency对象
AggregateCacheDependency cd = DependencyFacade.GetProductDependency ();
//将数据存储在缓存中,并添加必要的AggregateCacheDependency对象
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(product Timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
……
}
在上述代码中,AggregateCacheDependency是从.NET Framework 2.0开始新增的一个类,它负责监视依赖项对象的集合。当这个集合中的任意一个依赖项对象发生改变时,该依赖项对象对应的缓存对象都将被自动移除。在此不对AggregateCacheDependency进行详细说明,大家可以查阅相关资料进行扩展学习。
与业务逻辑层Product对象的GetProductsByCategory()方法相比,上述代码增加了缓存机制。当缓存内不存在相关数据项时,则直接调用业务逻辑层Product的GetProductsByCategory()方法来获取数据,并将其与对应的AggregateCacheDependency对象一起存储在缓存中。在ProductDataProxy类的每一个业务方法中都实例化了Product类,再调用Product类的相应方法,因此ProductDataProxy与Product之间属于依赖关系,这是标准代理模式的一种变形,可以按照标准代理模式对其进行改进,包括引入高层的抽象接口。
C#设计模式之代理模式(三)的更多相关文章
- C#设计模式(13)——代理模式(Proxy Pattern)
一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- C#设计模式:代理模式(Proxy Pattern)
一,什么是C#设计模式? 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问 二,代码如下: using System; using System.Collectio ...
- 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...
- 设计模式之代理模式之二(Proxy)
from://http://www.cnblogs.com/xwdreamer/archive/2012/05/23/2515306.html 设计模式之代理模式之二(Proxy) 0.前言 在前 ...
- 夜话JAVA设计模式之代理模式(Proxy)
代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...
- GOF23设计模式之代理模式
GOF23设计模式之代理模式 核心作用:通过代理,控制对对象的访问.可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理(即:AOP的微观实现) AOP(Asp ...
- js设计模式——1.代理模式
js设计模式——1.代理模式 以下是代码示例 /*js设计模式——代理模式*/ class ReadImg { constructor(fileName) { this.fileName = file ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- 第三章 --- 关于Javascript 设计模式 之 代理模式
第一.定义: 代理模式是为一个对象提供代用品或者占位符,以便控制对它的访问. 比如说,某男生小明想向他的女神 A 表白,刚好小明认识的一个女生B 和 女神A 是好朋友,那么小明就想让 女生B 帮忙送花 ...
随机推荐
- Randy Pausch’s Last Lecture
he University of Virginia American Studies Program 2002-2003. Randy Pausch ...
- archlinux安装交叉编译工具链
1. 在/usr/local下新建文件夹:arm [guo@archlinux local]$sudo mkdir arm 2. 将交叉编译工具拷贝到arm文件夹中 [guo@archlinux ...
- openstack、kvm、qemu-kvm、libvirt、xen的关系
虚拟化技术—基础(1) 本文围绕下面3个问题进行对虚拟化技术展开讨论: 1.虚拟化技术实现方式有哪些?虚拟化技术分哪些? 2.请分别通过kvm.xen工具来实现虚拟化系统的部署? 3.请描述opens ...
- (转)Openldap相关精品文章
1.运维咖啡吧 https://mp.weixin.qq.com/s__biz=MzU5MDY1MzcyOQ==&mid=2247483754&idx=1&sn=9f20d45 ...
- 第四次 Scrum Meeting
第四次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/4/8 22:00 30min 大运村1号楼3F 附Github仓库:WEDO 例会照片 工作情况总结(4.8) ...
- oracle 查看一个表中的记录是否被锁住
SELECT a.object_id, a.session_id, b.object_nameFROM v$locked_object a, dba_objects bWHERE a.object_i ...
- vi命令——修改文件内容
以下内容转载自http://blog.csdn.net/bruce0532/article/details/7842384 vi编辑器是所有Unix及Linux系统下标准的编辑器,介绍一下它的用法和一 ...
- Java基础25-静态代码块
/* 静态代码块 格式: static{ 静态代码块中执行语句 } 特点:随着类的加载而执行,并且只会执行一次,并且还优先于主函数. 作用:用于给类进行初始化 */ public class Test ...
- 20个最受欢迎的Linux命令(转)
本文根据 commandlinefu 网站的历史排名,筛选出了前 20 个得票最高的 Linux 命令.看看你都能熟练使用了吗? 1.以 root 帐户执行上一条命令 sudo !! 2.利用 Pyt ...
- net 预览文件 转换文件
预览SWF文件 swfobject.js (google浏览器 会阻止 需设置) @{ ViewBag.Title = "PdfPreview"; Layout = " ...