版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
工厂方法模式(FactoryMethod)——.NETTerrylee,20041工厂方法模式(FactoryMethod)——.NETTerrylee,200412概述在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口。如何应对这种变化?提供一种封装机制来隔离出“这个易变对象”的变化,从而保持系统中“其它依赖该对象的对象”不随着需求的改变FactoryMethod意图定义一个用户创建对象的接口,让子类决定实例化哪一个类。FactoryMethod化延迟到其子类。结构图生活中的例子工厂方法定义一个用于创建对象的接口,但是让子类决定实例化哪个类。压注成型演示了这种模式。塑料玩具制造商加工塑料粉,将塑料注入到希望形状的模具中。玩具的类别(车,人物等等)是由模具决定的。工厂方法解说这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节。FactoryMethod模式中,工厂类与产品类往往具有平行的等级结构,它们之间一一对应。现在我们考虑一个日志记录的例子(FactoryMethod模式,实际项目中的日志记录不会这么去做,也要比这复杂一些FileLogEventLog两种方式。在这里我们先不谈设计模式,那么这个日志记录的类就很好实现了:///<summary>///日志记录类///</summary>publicclassLog5 {67 publicvoidWriteEvent()8 {9 Console.WriteLine("EventLogSuccess!");10 }1112 publicvoidWriteFile()13 {14 Console.WriteLine("FileLogSuccess!");15 }1617 publicvoidWrite(stringLogType)18 {19 switch(LogType.ToLower())20 {case"event":WriteEvent();break;24case"file":WriteFile();break;28default:break;31 }32 }33 }34DatabaseLog,那就要修改Log语句在不断的变化,这样就引起了整个EventLogFileLog是两种完全不同的记录方式,它们之间不应该存在必然的联系,而应该把它们分别作为单独的对象来对待。///<summary>///EventLog类///</summary>publicclassEventLog5 {6 publicvoidWrite()7 {8 Console.WriteLine("EventLogWriteSuccess!");9 }10}11///<summary>///FileLog类///</summary>publicclassFileLog16 {17 publicvoidWrite()18 {19 Console.WriteLine("FileLogWriteSuccess!");20 }21}22进一步抽象,为它们抽象出一个共同的父类,结构图如下:实现代码:///<summary>///Log///</summary>publicabstractclass5 {6 publicabstractvoidWrite();7}8此时EventLog和FileLog类的代码应该如下:///<summary>///EventLog类///</summary>publicclassEventLog:Log5 {6 publicoverridevoidWrite()7 {8 Console.WriteLine("EventLogWriteSuccess!");9 }10}///<summary>///FileLog类///</summary>publicclassFileLog:Log15 {16 publicoverridevoidWrite()17 {18 Console.WriteLine("FileLogWriteSuccess!");19 }20}21DatabaseLogLogEventLogFileLog类,这样的设计满足了类程序中,我们要使用某一种日志记录方式,也许会用到如下这样的语句:EventLogeventlog=newEventLog();eventlog.Write();EventLogFactoryMethod模式了,每一个日志记录的对象就是工厂所生成的产品,既然有两种记录方式,那就需要两个不同的工厂去生产了,代码如下:///<summary>///EventFactory类///</summary>publicclassEventFactory5 {6 publicEventLogCreate()7 {8 returnnewEventLog();9 }10}///<summary>///FileFactory类///</summary>publicclassFileFactory15 {16 publicFileLogCreate()17 {18 returnnewFileLog();19 }20}21接口,结构图如下:实现代码如下:///<summary>///LogFactory类///</summary>publicabstractclassLogFactory5 {6 publicabstractLogCreate();7}8此时两个具体工厂的代码应该如下:///<summary>///EventFactory类///</summary>publicclassEventFactory:LogFactory5 {6 publicoverrideEventLogCreate()7 {8 returnnewEventLog();9 }10}///<summary>///FileFactory类///</summary>publicclassFileFactory:LogFactory15 {16 publicoverrideFileLogCreate()17 {18 returnnewFileLog();19 }20}21actoryMethod的过程。这样达到了我们应用程序和具体日志记录对象之间解耦的目的了吗?看一下此时客户端程序代码:///<summary>///App类///</summary>publicclassApp5 {6 publicstaticvoidMain(string[]args)7 {8 LogFactoryfactory=newEventFactory();910 Loglog=factory.Create();1112 13 }14}15Log对象的创建是频繁的,在这里我们可以把LogFactoryfactory=newEventFactory();Log只要修改一处为:LogFactoryfactory=newFileFactory();改,但是我们可以尽量做到只修改一处。其实利用.NET的特性,我们可以避免这种不必要的修改。下面我们利用.NET中的反射机制来相应的配置文件中设置如下:<appSettings><addkey="factoryName"value="EventFactory"></add></appSettings>4此时客户端代码如下:///<summary>///App类///</summary>publicclassApp5 {6 publicstaticvoidMain(string[]args)7 {8 stringstrfactoryName=ConfigurationSettings.AppSettings["factoryName"];9LogFactoryfactory;factory=(LogFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod."+strfactoryName);12Loglog=factory.Create();15 }16}17现在我们看到,在引进新产品(日志记录方式)增加新的产品类和新的工厂类(ASP.NETHTTP通道中的应用FactoryMethodASP.NETHTTPASP.NETHTTPystem.Web命名空间下的一个类,WEBServerHTTPSessionSystem.Web.HttpApplicationFactoryHttpRuntimeHTTPHttpContext实例,HttpRuntimeHttpApplicationHttpApplicationFactory.GetApplicationInstanceHttpContextGetApplicationInstanceHttpContext实例来确定针对这个请或者一个继承于ASP.Global_asax的类的实例)将直接从应用程序池中返回,否则针对该虚拟路径将创建一HttpApplication对象并返回。如下图所示:HttpApplicationFactory.GetApplicationInstanceHttpContext的参数,创建的所有对象(产品)HttpApplicationGetApplicationInstance的实现:1internalstaticIHttpHandlerGetApplicationInstance(HttpContextcontext)2 {3 if(HttpApplicationFactory._customApplication!=null)4 {5 returnHttpApplicationFactory._customApplication;6 }7 if(HttpDebugHandler.IsDebuggingRequest(context))8 {9 returnnewHttpDebugHandler();10 }11 if(!HttpApplicationFactory._theApplicationFactory._inited)12 {13 lock(HttpApplicationFactory._theApplicationFactory)14 {15 if(!HttpApplicationFactory._theApplicationFactory._inited)16 {tory.Init(context);tory._inited=true;19 }20 }21 }22 returnHttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);23}24System.Web.IHttpHandlerFactory我们来做进一步的探索,HttpApplicationHandler对象来处理资源请求,HttpApplication的主要任务就是找到真正处理请求的类。HttpApplication首先确定了HandlerMachine.config文件中的配置区<httphandlers>Machine.config中对*.aspx的System.Web.UI.PageHandlerFactory*.ashxSystem.Web.UI.SimpleHandlerFactoryIhttpHandlerFactory接口的具体类:<httpHandlers><addverb="*"path="*.aspx"type="System.Web.UI.PageHandlerFactory"/><addverb="*"path="*.ashx"type="System.Web.UI.SimpleHandlerFactory"/></httpHandlers>这个配置区建立了资源请求的类型和处理请求的类之间的一个映射集。如果一个.aspx页面发System.Web.UI.PageHandlerFactory调用IHttpHandlerFactoryGetHandlerHandler对象。当一sample.aspxPageHandlerFactoryASP.SamplePage_aspx对象(具体产品),如下图:IHttpHandlerFactory工厂:1publicinterfaceIHttpHandlerFactory2 {//MethodsIHttpHandlerGetHandler(HttpContextcontext,stringrequestType,stringurl,stringpathTranslated);voidReleaseHandler(IHttpHandlerhandler);6}7抽象工厂角色:IHttpHandlerFactory具体工厂角色:PageHandlerFactory抽象工厂角色:IHttpHandlerFactory具体工厂角色:PageHandlerFactory抽象产品角色:IHttpHandler具体产品角色:具体产品角色:ASP.SamplePage_aspx进一步去理解IHttpHandlerFactoryIHttpHandler这两个接口。1 publicclassHttpHandlerFactoryImpl:IHttpHandlerFactory{2IHttpHandlerIHttpHandlerFactory.GetHandler(HttpContextcontext,StringrequestType,Stringurl,StringpathTranslated){67 returnnewHttpHandlerImpl();89 10voidIHttpHandlerFactory.ReleaseHandler(IHttpHandlerhandler){/*no-op*/}1314}//HttpHandlerFactoryImpl1516 publicclassHttpHandlerImpl:IHttpHandler{1718 voidIHttpHandler.ProcessRequest(HttpContextcontext){1920 context.Response.Write("samplehandlerinvoked2122 }//ProcessRequest23
");24 boolIHttpHandler.IsReusable{get{returnfalse;}}2526}//HttpHandlerImpl27第二步需要在配置文件中建立资源请求类型和处理程序之间的映射。我们希望当请求的类型为sample时进入我们自定义的处理程序,如下:<httpHandlers><addverb="*"path="*.sample"type="HttpHandlerFactoryImpl,SampleHandler"/></httpHandlers>最后一步我们需要把文件扩展e映射到TI扩展(dll)IISASP.NET*.sample将简ASP.NETHTTP处理程序不会被调用。InternetWeb站点,选择属性,移动到主目录选项页,并点aspnet_isapi.dll文件路径,在扩展字段输入.sample。其它字段不用处理;该对话框如下所示:在.NETFrame
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年分红合作意向书模板
- 大班体育公开课教案《玩木棒》
- 2024年个人房产按揭贷款协议
- 中班音乐公开课教案及教学反思《袋鼠妈妈》
- 2024年创新版:虚拟现实教育培训系统开发合同
- 2024年‘绿色能源’项目投资与建设合作协议
- 2024年劳动合同新规则:管理者的指南针
- 中班体育教案:汽车拉力赛
- 中班音乐详案教案及教学反思《唐老鸭瘦身记》
- 8加几(教案)一年级上册数学人教版
- 供应室消防应急预案演练
- 校运会裁判员培训
- 潮湿相关性皮炎的护理
- 餐饮服务质量提升
- 洪恩识字配套字库完整版识字启蒙200字-生字组词句子完整版可打印-点读指读
- 幼儿园园长的幼教教研与项目管理
- 健康评估练习题大全(含答案)
- 新北师大版小学数学二年级上册《六-测量:课桌有多长》-公开课教案-1
- 2024年黑龙江建筑职业技术学院高职单招(英语/数学/语文)笔试历年参考题库含答案解析
- 构建文明校园共同创造和谐学园
- 铁路边坡水害分析报告
评论
0/150
提交评论