免费按模板制作微网站,微网站免费开发平台,水务 网站建设,上海网站建设公司 珍岛原文地址#xff1a;http://www.cnblogs.com/QinBaoBei/archive/2010/05/18/1737866.html 为了深刻点理解代理模式#xff0c;我们先来看一个 Demo #xff0c; 首先这个 Demo 是用来测试 QQ 号码是否在线#xff0c; 这里涉及到的内容是 Web 服务的使用#xff0c; 这个 …原文地址http://www.cnblogs.com/QinBaoBei/archive/2010/05/18/1737866.html 为了深刻点理解代理模式我们先来看一个 Demo 首先这个 Demo 是用来测试 QQ 号码是否在线 这里涉及到的内容是 Web 服务的使用 这个 Web 服务所在地址为 http://webservice.webxml.com.cn/webservices/qqOnlineWebService.asmx 如果有不懂 Web 服务的还可以查看笔者一篇涉及 Web 服务的文章 http://www.cnblogs.com/QinBaoBei/archive/2010/03/30/1700898.html 然后我便将上面的验证 QQ 是否在线的这个 Web 服务引入到我的项目中 并且给这个 Web 服务命名为 WebService.TestQQ 然后就是来编写类了 主要是一个 TestResult 类这个类的作用就是来完成访问 Web 服务返回验证结果 其具体代码如下 namespace ProxyQQ { public static class TestResult { public static string GetResult(string qqNum) { //调用引用的 Web 服务自命名为 WebService.TestQQ WebService.TestQQ.qqOnlineWebService testQQ new WebService.TestQQ.qqOnlineWebService(); return testQQ.qqCheckOnline(qqNum); } } } 然后就是要编写客户端了我这里使用的是一个 WinForm 应用程序来实现的 这个项目中唯一一个窗体 TestQQ 的代码如下 using System; using System.Windows.Forms; namespace ProxyQQTest { public partial class TestQQ : Form { public TestQQ() { InitializeComponent(); } private void btnQuery_Click(object sender, EventArgs e) { //调用 ProxyQQ 命名空间下的静态类 TestResult 的 //静态方法 GetResult()来判断 QQ 状态 string result ProxyQQ.TestResult.GetResult(txtQQNum.Text.Trim()); string msg String.Empty; switch (result) { case Y: msg 该 QQ 在线; break; case N: msg 该 QQ 离线; break; case E: msg 该 QQ 号码不存在; break; case A: msg 商业用户验证失败; break; case V: msg 免费用户超过数量; break; default: break; } MessageBox.Show(msg, 提示, MessageBoxButtons.OK, MessageBoxIcon.Information); } } } 下面就来查询一下 QQ 号码咯 然后我让我的 QQ 上线再来查看 好说了这么多了感觉是在介绍 Web 服务似的 但是请不要误会本篇博文是来介绍代理模式的而非 Web 服务 下面我们就从上面的这个 Demo 来谈谈代理模式 其实上面谈到的 Demo 就是代理模式的一种最典型的应用--远程代理 先来看上面的 Demo 中我添加的那个 Web 服务 当我在我的项目中添加了 Web 服务后呢 大家可以看到会在项目中自动生成一个 WebReference 的文件夹以及一些文件 其实这些就是代理了 您看我在应用程序中只是使用了下面一丁点代码 //调用引用的 Web 服务自命名为 WebService.TestQQ WebService.TestQQ.qqOnlineWebService testQQ new WebService.TestQQ.qqOnlineWebService(); return testQQ.qqCheckOnline(qqNum); 我们在客户端只需要通过这一丁点代码就可以完成访问 Web 服务并且返回结果 也可以说成是客户端通过调用代理来完成远程访问并返回结果。 下面就来看看什么是远程代理 远程代理可以看做另一个服务器上的对象在本地服务器上的代表 调用代理的方法就会被代理通过网络来转发到远程执行并且结果会通过网络返回给代理 然后再由代理将结果转发给客户。 其实上面对远程代理的定义还是不明确的就拿 Web 服务来说的话您也可以调用你自己的项目中的 Web 服务的 所以完整的远程代理的定义是为一个不同地址空间中的对象提供一个局部代表对象 不过这个不同的地址空间呢可以在您的本地机也可以在远程机器上 所以在上面的 Demo 中 就可以把 WebService.TestQQ.qqOnlineWebService 代理对象看做是 验证 QQ 号码这个对象这里看做一个对象它是被代理的对象在本地机器也就是我的项目中上的代理对象 而后我在客户端中便只需要对这个代理对象进行访问和操作就 OK 了其他的内容就交给代理对象来完成了 这是典型的代理模式。 上面呢介绍的只是代理模式的一种最典型的应用也就是远程代理而下面就要来介绍代理模式的一些具体内容了 什么是代理模式 代理模式为另一个对象提供一种代理换句话说就是替身以控制对这个对象的访问使用代理模式创建代理对象 让这个代理对象控制某个对象的访问。 下面就来看看代理模式的结构类图 从上面的结构类图可以看出代理类和具体主题类都继承子抽象主题类 何为要这样实现继承呢 很简单的由于 Proxy 和 RealSubject 均继承自 Subject 这个抽象主题类 并且在 Proxy 和 RealSubject 中均实现了 Request 方法 所以在需要使用 RealSubject 的地方便可以使用 Proxy 来替代 换句话说的话可以认为 Proxy 和 RealSubject 是同一类型 由于使用了 Proxy 来替代 RealSubject 所以便实现了通过 Proxy 来代理 RealSubject 同时在 Proxy 这个代理类中保存和维护了一个 RealSubject 对象 当然就在一定程度上实现了通过 Proxy 来控制 RealSubject 。 下面还是先来看看这个代理模式的最基本的结构实现吧 Subject 类 namespace Proxy { public abstract class Subject { public abstract void Request(); } } Proxy 类 using System; namespace Proxy { public class Proxy:Subject { private RealSubject realSubject; public override void Request() { Console.WriteLine(this.GetType().ToString()); if (realSubject null) { realSubject new RealSubject(); } realSubject.Request(); } } } RealSubject 类 using System; namespace Proxy { public class RealSubject:Subject { public override void Request() { Console.WriteLine(this.GetType().ToString()); } } } 客户端代码 using System; namespace ProxyTest { class Program { static void Main(string[] args) { Proxy.Subject proxy new Proxy.Proxy(); proxy.Request(); Console.ReadKey(); } } } 光看上面的代码和效果我想大家很难明白是怎么一回事那么还请看下面的解释然后再回过头结合代码来看 那么大家应该就可以明白代理模式到底是咋一回事了 首先可以看到 Proxy 和 RealSubject 这两个类都继承自抽象类 Subject 同时均实现了在抽象类 Subject 类中定义的 Request 方法 这样的话在某一层意义上来说Proxy 就是 RealSubject 的替身了 因为他们的抽象类型都是一样的所以便可以在 RealSubject 出现的地方使用 Proxy 来替代了 比如在上面的例子中我本来的意义是要在客户端中调用 RealSubject 的 Request 方法的 所以本来在客户端代码中应该如下写的 Proxy.Subject realSubject new Proxy.RealSubject(); realSubject.Request(); 而事实上并非这样我是通过实例化一个 Proxy 类来完成操作的因为我在 Proxy 中保存了一个 RealSubject 对象 并且在 Proxy 类的 Request 方法中调用了 RealSubject 的 Request 方法 所以便是代理实现了调用 RealSubject 的 Request 方法 在这里我想就有疑问了那就是我为什么一定要在客户端来通过 Proxy 代理完成这个操作 而不是直接实例化 RealSubject 对象来完成 Request 操作了 其实这里涉及到的便是代理模式的具体应用了前面看了一种应用也就是远程代理 下面我们来看另外一种代理模式的应用也就是虚拟代理 比如我要加载一个很大的视频文件或者是图片文件比如 800 像素拍下的照片 2M 此时由于网络速度慢的缘故在加载的时候费个什么几秒钟那是非常常见的但是就是在这几秒钟中 难道您就让用户干巴巴的等着吗要我是用户的话看着半天没反应的浏览器或者是窗体 我想我还是关闭算了吧 那么我们有什么办法来解决上面的问题呢 其实有一种比较好的办法就是当图片在下载时可以发布一个提示消息比如“正在下载中请等待” 做的好一点的话还可以显示一张本地的小图片这样会更炫 然后等下载完成后便将这些提示消息去掉然后显示图片就 OK 了这样可以极大的提高用户体验 其实这种效果在很多地方都常见了而这就是通过虚拟代理来解决的 我们先来看一下腾讯主页上这种效果吧 下面就来看如何通过虚拟代理来完成上面的这种效果 我们就来看类了 首先是 Subject 这个抽象类在这里是 LoadImage 来充当 namespace ProxyVirtual { public abstract class LoadImage { public abstract void LoadImageRequest(); } } 然后是 Proxy 这个代理类这里由 ProxyLoadImage 来充当 using System.Windows.Forms; using System.Drawing; using System.Threading; namespace ProxyVirtual { public class ProxyLoadImage : LoadImage { //这里要保存一个具体主题类的引用 //这样才能够实现控制具体主题了 RealLoadImage private RealLoadImage realLoadImage; private PictureBox pcBox; public ProxyLoadImage(PictureBox pcBox, RealLoadImage realLoadImage) { this.pcBox pcBox; this.realLoadImage realLoadImage; } public override void LoadImageRequest() { //首先是要实例化一个线程 Thread thread new Thread(ThreadMethod); //然后就是要启动这个线程了 thread.Start(); } private void ThreadMethod() { //将整个提示用户还在下载的图片小图片 //和正在下载的图片大图片放在同一个线程中 //可以防止其他线程对整个应用程序进行干扰 pcBox.Image Image.FromFile(SquareCircle.gif); realLoadImage.LoadImageRequest(); } } } 还有一个就是具体主题类 RealLoadImage 类了 using System.Windows.Forms; using System.Drawing; using System.Net; namespace ProxyVirtual { public class RealLoadImage : LoadImage { private string strUrl; private PictureBox pcBox; public RealLoadImage(string strUrl, PictureBox pcBox) { this.strUrl strUrl; this.pcBox pcBox; } public override void LoadImageRequest() { //发出对指定 URL 路径的请求这里是请求一张图片 WebRequest request WebRequest.Create(strUrl); //返回对请求的响应结果 WebResponse response request.GetResponse(); //从网络资源中返回数据流然后给图片框显示 pcBox.Image Image.FromStream(response.GetResponseStream()); } } } 然后就是客户端代码了这里是一个 Form 的 Code-Behind using System; using System.Windows.Forms; namespace ProxyVirtualTest { public partial class Test : Form { public Test() { InitializeComponent(); } private void Test_Load(object sender, EventArgs e) { ProxyVirtual.LoadImage loadImage new ProxyVirtual.ProxyLoadImage(this.pcBox, new ProxyVirtual.RealLoadImage( http://images.cnblogs.com/cnblogs_com/qinbaobei/6.jpg, this.pcBox)); //调用代理类的 LoadImageRequest loadImage.LoadImageRequest(); } } } 下面也把效果给出来刚开始加载的时候效果是 当下载完成以后便会出现 上面的这张图片呢是我的博客中的一张图片我通过 URL 来下载到我的应用程序当中。 下面我再给出上面这个 Demo 的类图大家可以拿这个类图和最开始的代理模式的结构类图比较比较 我们不谈别的内容光从上面的这幅类图中便可以看出上面的 Demo 使用的就是代理模式 下面我们还再来具体的谈一下何为虚拟代理 虚拟代理是作为创建大的对象的代理类一般来说创建一个对象需要消耗比较大的资源时 可以通过虚拟代理来实现这个对象只有在需要的时候才会被真正创建 可以通过使用代理这个代理不怎么耗资源来在必要的时候将被代理的对象加载 也就是通过不怎么耗资源的代理来控制什么时候需要加载比较耗资源的被代理对象 在上面的 Demo 中大的图片就是比较耗资源的所以通过一个不怎么耗资源的小图片先来代理它 在真正需要这个大图片的时候再通过代理来加载。 再看一个虚拟代理的应用那就是当您打开一个有很多图片的网页时 一般来说文字是全部可以看到的会在加载网页的时候全部下载过来 而图片却必须要一张一张的下载才能看得 比如您将滑轮往下滚会看到一些图片并没有显示出来只是在那里留出一个方框 而真实的图片就需要等待才能显示 那些未打开的图片框就是通过虚拟代理来替代了真实的图片 此时代理存储了真实图片的路径和大小所以在也没上才会出现图片的方框而并没有真实的图像。 在上面浏览器中使用代理模式的好处是什么呢很明显通过使用虚拟代理优化了下载。 上面呢重点介绍了代理模式的两种应用即远程代理和虚拟代理其实呢代理模式还有很多变种的 既然是变种的话基本上就差不太多远啦 比如安全代理智能引用代理缓存代理写入时复制代理防火墙代理等等 在这里就不做一一介绍了如果有想了解的可以 Google 或者是 Bing 一下就会出来一大堆了 还有就是 TerryLee 的博客上也有一点点介绍的感兴趣的可以去看看 转载于:https://www.cnblogs.com/fcsh820/archive/2010/05/18/1738088.html