注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天涯倦客的博客

祝福你朋友永远快乐!

 
 
 

日志

 
 

工厂方法模式(Factory Method)二  

2011-03-17 10:05:14|  分类: 设计模式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

ASP.NET HTTP通道中的应用

Factory Method模式在ASP.NET HTTP通道中我们可以找到很多的例子。ASP.NET HTTP通道是System.Web命名空间下的一个类,WEB Server使用该类处理接收到的HTTP请求,并给客户端发送响应。HTTP通道主要的工作有Session管理,应用程序池管理,缓存管理,安全等。

System.Web.HttpApplicationFactory

HttpRuntimeHTTP通道的入口点,它根据每一个具体的请求创建一个HttpContext实例, HttpRuntime并没有确定它将要处理请求的HttpApplication对象的类型,它调用了一个静态的工厂方法HttpApplicationFactory.GetApplicationInstance,通过它来创建HttpContext实例。GetApplicationInstance使用HttpContext实例来确定针对这个请求该响应哪个虚拟路径,如果这个虚拟路径以前请求过,HttpApplication(或者一个继承于ASP.Global_asax的类的实例)将直接从应用程序池中返回,否则针对该虚拟路径将创建一个新的HttpApplication对象并返回。如下图所示:

工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

HttpApplicationFactory.GetApplicationInstance带有一个类型为HttpContext的参数,创建的所有对象(产品)都是HttpApplication的类型,通过反编译,来看一下GetApplicationInstance的实现:

 1工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客internal static IHttpHandler GetApplicationInstance(HttpContext context)
 2工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客{
 3工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      if (HttpApplicationFactory._customApplication != null)
 4工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      {
 5工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客            return HttpApplicationFactory._customApplication;
 6工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      }

 7工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      if (HttpDebugHandler.IsDebuggingRequest(context))
 8工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      {
 9工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客            return new HttpDebugHandler();
10工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      }

11工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      if (!HttpApplicationFactory._theApplicationFactory._inited)
12工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      {
13工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客            lock (HttpApplicationFactory._theApplicationFactory)
14工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客            {
15工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客                  if (!HttpApplicationFactory._theApplicationFactory._inited)
16工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客                  {
17工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客                        HttpApplicationFactory._theApplicationFactory.Init(context);
18工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客                        HttpApplicationFactory._theApplicationFactory._inited = true;
19工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客                  }

20工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客            }

21工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      }

22工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      return HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
23工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客}

24工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

System.Web.IHttpHandlerFactory

我们来做进一步的探索,HttpApplication实例需要一个Handler对象来处理资源请求, HttpApplication的主要任务就是找到真正处理请求的类。HttpApplication首先确定了一个创建Handler对象的工厂,来看一下在Machine.config文件中的配置区<httphandlers>,在配置文件注册了应用程序的具体处理类。例如在Machine.config中对*.aspx的处理将映射到System.Web.UI.PageHandlerFactory 类,而对*.ashx的处理将映射到System.Web.UI.SimpleHandlerFactory 类,这两个类都是继承于IhttpHandlerFactory接口的具体类

工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客<httpHandlers>
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" />
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
<add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory" />
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
</httpHandlers>
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

这个配置区建立了资源请求的类型和处理请求的类之间的一个映射集。如果一个.aspx页面发出了请求,将会调用System.Web.UI.PageHandlerFactory类,HttpApplication调用接口IHttpHandlerFactory中的工厂方法GetHandler来创建一个Handler对象。当一个名为sample.aspx的页面发出请求时,通过PageHandlerFactory将返回一个ASP.SamplePage_aspx对象(具体产品),如下图:

工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

IHttpHandlerFactory工厂:

1工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客public interface IHttpHandlerFactory
2工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客{
3工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      // Methods
4工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
5工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      void ReleaseHandler(IHttpHandler handler);
6工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客}

7工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

IHttpHandlerFactory.GetHandler是一个工厂方法模式的典型例子,在这个应用中,各个角色的设置如下:

抽象工厂角色:IHttpHandlerFactory

具体工厂角色:PageHandlerFactory

抽象产品角色:IHttpHandler

具体产品角色:ASP.SamplePage_aspx

进一步去理解

理解上面所说的之后,我们就可以去自定义工厂类来对特定的资源类型进行处理。第一步我们需要创建两个类去分别实现IHttpHandlerFactory IHttpHandler这两个接口。

 1工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客public class HttpHandlerFactoryImpl:IHttpHandlerFactory {
 2工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   
 3工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   IHttpHandler IHttpHandlerFactory.GetHandler(
 4工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      HttpContext context, String requestType, 
 5工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      String url, String pathTranslated ) {
 6工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
 7工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客         return new HttpHandlerImpl();
 8工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客         
 9工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   }
//IHttpHandlerFactory.GetHandler
10工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
11工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   void IHttpHandlerFactory.ReleaseHandler(
12工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      IHttpHandler handler) /*no-op*/ }
13工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
14工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客}
//HttpHandlerFactoryImpl
15工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
16工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客public class HttpHandlerImpl:IHttpHandler {
17工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
18工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   void IHttpHandler.ProcessRequest(HttpContext context) {
19工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      
20工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      context.Response.Write("sample handler invoked工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客");
21工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      
22工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   }
//ProcessRequest
23工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
24工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   bool IHttpHandler.IsReusable get return false; } }
25工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
26工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客}
//HttpHandlerImpl
27工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

第二步需要在配置文件中建立资源请求类型和处理程序之间的映射。我们希望当请求的类型为*.sample时进入我们自定义的处理程序,如下:

工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客<httpHandlers>
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客   
<add verb="*" path="*.sample" 
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客      type
="HttpHandlerFactoryImpl,SampleHandler" />
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客
</httpHandlers>
工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

最后一步我们需要把文件扩展*.sample映射到ASP.NET ISAPI扩展DLLaspnet_isapi.dll)上。由于我们已经建立了用于处理新扩展文件的处理程序了,我们还需要把这个扩展名告诉IIS并把它映射到ASP.NET。如果你不执行这个步骤而试图访问*.sample文件,IIS将简单地返回该文件而不是把它传递给ASP.NET运行时。其结果是该HTTP处理程序不会被调用。

运行Internet服务管理器,右键点击默认Web站点,选择属性,移动到主目录选项页,并点击配置按钮。应用程序配置对话框弹出来了。点击添加按钮并在可执行字段输入aspnet_isapi.dll文件路径,在扩展字段输入.sample。其它字段不用处理;该对话框如下所示:

工厂方法模式(Factory Method)二 - 海里的贝壳 - apple的博客

.NET Framework中,关于工厂模式的使用有很多的例子,例如IEnumerableIEnumerator就是一个Creator和一个ProductSystem.Security.Cryptography中关于加密算法的选择,SymmetricAlgorithmAsymmetricAlgorithmHashAlgorithm分别是三个工厂,他们各有一个静态的工厂方法CreateSystem.Net.WebRequest .NET Framework 的用于访问 Internet 数据的请求/响应模型的抽象基类。使用该请求/响应模型的应用程序可以用协议不可知的方式从 Internet 请求数据。在这种方式下,应用程序处理 WebRequest 类的实例,而协议特定的子类则执行请求的具体细节。请求从应用程序发送到某个特定的 URI,如服务器上的 Web 页。URI 从一个为应用程序注册的 WebRequest 子代列表中确定要创建的适当子类。注册 WebRequest 子代通常是为了处理某个特定的协议(如 HTTP  FTP),但是也可以注册它以处理对特定服务器或服务器上的路径的请求。有时间我会就.NET Framework中工厂模式的使用作一个专题总结。

实现要点

1.  Factory Method模式的两种情况:一是Creator类是一个抽象类且它不提供它所声明的工厂方法的实现;二是Creator是一个具体的类且它提供一个工厂方法的缺省实现。

2.  工厂方法是可以带参数的。

3.  工厂的作用并不仅仅只是创建一个对象,它还可以做对象的初始化,参数的设置等。

效果

1.  用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。

2.  Factory Method模式通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。

适用性

在以下情况下,适用于工厂方法模式:

1.       当一个类不知道它所必须创建的对象的类的时候。

2.       当一个类希望由它的子类来指定它所创建的对象的时候。

3.       当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

总结

Factory Method模式是设计模式中应用最为广泛的模式,通过本文,相信读者已经对它有了一定的认识。然而我们要明确的是:在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。Factory Method要解决的就是对象的创建时机问题,它提供了一种扩展的策略,很好地符合了开放封闭原则。__________________________________________________________________________________

参考文献:

《设计模式》(中文版)

MSDN:《Exploring the Factory Design Pattern

DesignPatternsExplained

作者:TerryLee
出处:http://terrylee.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  评论这张
 
阅读(530)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017