定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
以.NET Framework 2.0 System.Web、System.Web.UI中类为例
System.Web.IHttpHandler
public interface IHttpHandler
{
bool IsReusable { get; }
void ProcessRequest(HttpContext context);
}
System.Web.IHttpHandlerFactory2
public interface IHttpHandlerFactory2
{
IHttpHandler GetHandler(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath);
}
System.Web.UI.Page
Code
public class Page : TemplateControl, IHttpHandler
{
//
public bool IsReusable
{
get { return false; }
}
//
public virtual void ProcessRequest(HttpContext context)
{
//
}
//
}
System.Web.UI.PageHandlerFactory
Code
public class PageHandlerFactory : IHttpHandlerFactory2
{
private bool _isInheritedInstance;
protected internal PageHandlerFactory()
{
// Check whether this is the exact PageHandlerFactory, or a derived class
_isInheritedInstance = (GetType() != typeof(PageHandlerFactory));
}
public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
{
Debug.Trace("PageHandlerFactory", "PageHandlerFactory: " + virtualPath);
// This should never get called in ISAPI mode but currently is in integrated mode
// Debug.Assert(false);
return GetHandlerHelper(context, requestType, VirtualPath.CreateNonRelative(virtualPath), path);
}
IHttpHandler IHttpHandlerFactory2.GetHandler(HttpContext context, String requestType,
VirtualPath virtualPath, String physicalPath)
{
// If it's a derived class, we must call the old (less efficient) GetHandler, in
// case it was overriden
if (_isInheritedInstance) {
return GetHandler(context, requestType, virtualPath.VirtualPathString, physicalPath);
}
return GetHandlerHelper(context, requestType, virtualPath, physicalPath);
}
public virtual void ReleaseHandler(IHttpHandler handler) { }
private IHttpHandler GetHandlerHelper(HttpContext context, string requestType,
VirtualPath virtualPath, string physicalPath)
{
Page page = BuildManager.CreateInstanceFromVirtualPath(
virtualPath, typeof(Page), context, true /*allowCrossApp*/, true /*noAssert*/) as Page;
if (page == null)
return null;
page.TemplateControlVirtualPath = virtualPath;
return page;
}
}
默认Web.Config配置
Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- -->
<system.web>
<!-- -->
<httpHandlers>
<!-- -->
<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="true"/>
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="true"/>
<add path="*.asmx" verb="*" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false"/>
<!-- -->
</httpHandlers>
<!-- -->
</system.web>
<!-- -->
</configuration>
IHttpHandlerFactory2是IHttpHandler的工厂,通过它来生成不同的HttpHandler对象。
HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。
HttpHandlerFactory,是一个HTTP请求到达这个HttpHandler Factory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。
在以下情况下,适用于工厂方法模式:
1. 当一个类不知道它所必须创建的对象的类的时候。
2. 当一个类希望由它的子类来指定它所创建的对象的时候。
3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。