从无工厂到工厂方法
从无工厂到工厂方法
工厂方法模式 - 从新关键字中减轻
介绍
当我们听到“设计模式”这个词时,我们头脑中的第一个问题是“什么是设计模式”?
设计模式是针对软件开发中经常出现的问题的可重复使用和记录的解决方案。
四人帮(GOF)将“设计模式”分为3类
- 创力
- 结构
- 行为的
当我开始学习设计模式时,我发现Factory方法是一个非常有趣的模式。它是最有争议和最困惑的创作模式之一。人们在理解这种模式时有很多混乱。
首先让我让大家清楚,没有什么像工厂模式(根据GOF设计模式列表),GOF有一些叫做工厂方法模式的东西。(在这个阶段的后面我们会碰到这两个术语)
在本文中,我将介绍两个虚构人物亚历山大(.NET开发人员)和托马斯(IT研究所首席执行官Programmer24X7)。
故事从托马斯接触亚历山大的那天开始,并要求他在他的内部项目“课程管理系统”中担任建筑师的角色。我们将看到亚历山大如何日益发展自己对工厂方法模式的了解,以及他如何最终提出一个很好的解决方案。
在开始阅读这篇文章之前,从我身边提供一些小小的建议,除了你以外,还要保留一些零食,因为这将是一个疲惫的6天的故事。基本上我正在努力玩你的耐心。别担心只是在开玩笑。它会很有趣,你会喜欢阅读这篇文章,在这篇文章的最后,你可以自豪地说“我知道工厂方法模式”。
所以放松一下,让我们开始学习工厂方法模式
指数
- 第一天 - 亚历山大如何开始? - 方法1 - 无工厂方法
- 第二天 - 亚历山大·继续吗? - 方法2 - 简单的工厂方法
- 第3天 - 方法3 - 多个简单的工厂方法
- 第4天 - 关于多个简单的工厂方法的讨论
- 第4天 - 夜晚 - 对象噩梦
- 第5天 - 方法4 - 工厂方法方法
- 第6天 - 最终演示
- 其他方法和想法
- 源代码下载
第1天
亚历山大(我们的.NET开发人员)收集了Thomas(我们的Programmer24X7 CEO)的要求。他的主要要求之一是建立一个将管理Programmer24X7(技术学院)提供的在线课程的模块。
亚历山大怎么样?
我)系统亚历山大将要开发课程管理系统,所以第一个合乎逻辑的步骤就是开始创建课程库。
II)下一步将创建课程实例并构建UI - 用户界面。以下是每个程序员认为最明显的代码,甚至亚历山大也是如此。
方法1 - 无工厂方法
AbstractCourse objCourse = null;
switch(StrUserInput)
{
case "N":
objCourse = new NetCourse();
break;
case "J":
objCourse = new JavaCourse();
break;
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
//Display objCourse.CourseName and objCourse.CourseDuration
最后一步 - 示范
自从模块准备好以来,亚历山大对托马斯也是一样的,托马斯对建筑的感觉很好。亚历山大的努力得到了很好的赞赏,但这一切都没有结束。然后,他接受了下一个逻辑层面的要求,他就应用程序分享了他的进一步计划。他说,
- 他计划添加新的在线课程,如C ++,VC ++等,并希望在将来停止几门课程。
- 将来在Programmer24X7离线课程将要进行,所以确保使一切可重用。
托马斯要求亚历山大根据这个先进的范围进行更改。那么亚历山大呢就是一个大惊喜
这是像煎锅一样,但进入亚历山大的火情。
“添加新课程意味着”,打开现有的UI代码现有逻辑(添加更多的开关案例,并在将来删除一些现有的案例)。
考虑建筑师的情况,建筑施工结束后,被要求在1楼和2楼之间再增加一层,建筑物不会崩溃。
方法问题1
- 当课程库修改时,SOLID原则OCP(Open Closed Principle)将被违反。(OCP说,软件实体(类,模块,功能等)应该是开放的扩展,但关闭修改)
- 在另一个用户界面中重复使用相同的(课程创建)逻辑是不可能的。
亚历山大学什么?
亚历山大认识到软件开发的一个重要内容,并学到了一个很大的教训:“变革是开发的重要组成部分,系统应该能够轻松适应这种变化,而不需要修改现有的测试部分。”
不是很有趣,改变系统,但不要改变代码。好吧,我们来看看我们如何做到这一点。
第二天
亚历山大·亚历山大·
亚历山大第二天清晨起床。咖啡在他手中,但心中仍在考虑手头的问题。他从黑暗的天空找到正确的星星是非常困难的,但是最终他设法找到了月球,而那里就是方法2。
|
|
方法2 - 简单的工厂方法
在第一种方法中,UI正在创建课程对象。
![]() |
现在,如果将对象创建的力量从UI中取出并将其赋予其他人,那将是如何。这里别人叫Simple Factory类。 |
什么是简单工厂?
Simple Factory是一个具有公共静态方法的类,它将根据所获取的输入实际执行对象创建任务。
public class CourseFactory
{
public static AbstractCourse CreateCourse(string ScheduleType)
{
AbstractCourse objCourse = null;
switch(ScheduleType)
{
case "N":
objCourse = new NetCourse();
break;
case "J":
objCourse = new JavaCourse();
break;
//Add more case conditions here for VC++ and C++
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
return objCourse;
}
}
UI
AbstractCourse objCourse = CourseFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration
方法的优点2
- 每当引入新课程时,更改的是工厂不是客户端代码。
- 由于工厂是类,任何人都可以使用它有权访问。简而言之,课程逻辑现在可以重复使用。
最后一步 - 示范
晚些时候,亚历山大达到了Programmer24X7办公室来展示这一修订的架构。但在亚历山大开始表达自己的焦虑之前,又出现了一个令人惊讶的要求。托马斯说:“我认为,如果我们为企业时间表增加一个UI,那会更好。原因是,现在我的企业培训计数增加了很多,所以我变得不可能管理。“
I)现在我们应该做的第一件事是改变课程图书馆(因为我们需要添加公司课程)。
II)为我们的Simple Factory类添加更多的案例条件。
public class CourseFactory
{
public static AbstractCourse CreateCourse(string ScheduleType)
{
AbstractCourse objCourse = null;
switch(ScheduleType)
{
case "CN":
objCourse = new CNetCourse();
break;
case "CJ":
objCourse = new CJavaCourse();
break;
case "CB":
objCourse = new CBICourse();
break;
case "OJ":
objCourse = new OJavaCourse();
break;
case "ON":
objCourse = new ONetCourse();
break;
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
return objCourse;
}
}
方法问题2
使用简单工厂方法可以很容易地覆盖新的要求,那么呢?
- 尽管所有类都源自抽象课程,但在单个简单工厂中添加了五种情况违反SOLID原理SRP - 单一责任原则。(SRP说一个类应该只有一个原因要改变。)
这里Factory类将被更改- 每当新的公司课程介绍或修改。
- 每当新的在线课程介绍或修改。
所以这个Simple Factory解决方案在当前的问题环境中不会运行。
第3天
我们列出我们的所有要求。
- 我们需要工厂的在线课程
- 我们需要企业课程的工厂
- 我们不想为两个模块创建单个工厂。
- 如何使用多个简单的工厂。
- OnlineCourseFactory
- CorporateCourseFactory
方法3 - 多个简单的工厂方法
在这种方法中,我们将有多个简单的工厂,每个工厂都有一个静态方法,它将根据它获得的输入创建一个实例。
![](https://www.codeproject.com/images/arrow-up-16.png)
public class CorporateCourseFactory
{
public static AbstractCourse CreateCourse(string ScheduleType)
{
AbstractCourse objCourse = null;
switch(ScheduleType)
{
case "N":
objCourse = new CNetCourse();
break;
case "J":
objCourse = new CJavaCourse();
break;
case "B":
objCourse = new CBICourse();
break;
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
return objCourse;
}
}
public class OnlineCourseFactory
{
public static AbstractCourse CreateCourse(string ScheduleType)
{
AbstractCourse objCourse = null;
switch(ScheduleType)
{
case "N":
objCourse = new ONetCourse();
break;
case "J":
objCourse = new OJavaCourse();
break;
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
return objCourse;
}
}
在线课程用户界面
AbstractCourse objCourse = OnlineCourseFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration
企业课程用户界面
AbstractCourse objCourse = CorporateCourseFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration
一切解决问题解决了。
第4天
亚历山大第二天到达Programmer24X7并向Thomas解释了托马斯的回答是什么?是好是坏?
在研究建筑之后,我们进行了大量讨论的小脚本。
托马斯:对不起,亚历山大,但我不认为这个解决方案会奏效。
亚历山大:为什么先生
托马斯:看到,对于每个课程组,都有一个单独的工厂。(OnlineCourseFactory,CoporateCourseFactory)。
但是,您将如何对每个工厂进行控制。我的意思是如何确保每个工厂正确地创建对象,例如,如何确保每个工厂遵循公司标准,并在返回对象之前创建课程材料和计划。
有可能在未来有一家工厂表示,OfflineCourseFactory被添加用于管理离线课程,并且不知不觉中它违反了公司标准,并以自己的方式创建课程材料。
亚历山大:你是对的先生。让我考虑一个完整的证明和最终的解决方案,给我一天。
托马斯:没有问题亚历山大 祝你今天愉快。
方法问题3
- 每个工厂都是独立的。定义工厂没有严格的规定。在这种方式下,每个工厂都可以有自己的结构和标准。
第4天 - 晚上
我们列出我们的所有要求。
- 我们需要工厂的在线课程
- 我们需要企业课程的工厂
- 我们不想为两个模块创建单个工厂。
- 应该有一些规则,如何界定每个人都应该遵循的工厂。
- 如果我们使用方法3的组合(即每当需要创建新工厂)
加上继承或组合时,它将如何。
- 是时候睡觉了。
第5天
亚历山大昨晚在说什么?
- 将所有常见功能放在一个地方(类),并在所有工厂中重用它们。
我们称之为“ReusbaleClass”用于讨论目的。我们需要可重用性 -
我们可以通过两种方法来实现。- 继承 - 从ReusbaleClass派生所有工厂 - >调用解决方案1
- 与组合 - 所有工厂将有一个类型为ReusbaleClass的成员 - >调用它解决方案2
- 让工厂覆盖ReusbaleClass中定义的某些功能(每个工厂都不同)。
- 我们需要覆盖意味着解决方案1将适合完美。
方法4 - 工厂方法方法
简而言之,我们需要一个这样的类,它将执行所有常见任务并暴露虚拟或抽象函数。
所以让我们创建一个AbstractCourseFactory,它将使用一个额外的可覆盖(虚拟或抽象)方法来封装通用的功能,然后重新创建我们的OnlineCourseFactory和CorporateCourseFactory。
public abstract class AbstractCourseFactory
{
public AbstractCourse CreateCourse(string ScheduleType)
{
AbstractCourse objCourse = this.GetCourse(ScheduleType);
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
return objCourse;
}
public abstract AbstractCourse GetCourse(string ScheduleType);
}
请注意GetCourse方法是抽象的
现在,每个(每个工厂)都将容易地覆盖这个GetCourse方法。
![](https://www.codeproject.com/images/arrow-up-16.png)
public class CorporateCourseFactory:AbstractCourseFactory
{
public override AbstractCourse GetCourse(string ScheduleType)
{
switch(ScheduleType)
{
case "N":
return new CNetCourse();
case "J":
return new CJavaCourse();
default:
return null;
}
}
}
public class OnlineCourseFactory : AbstractCourseFactory
{
public override AbstractCourse GetCourse(string ScheduleType)
{
switch(ScheduleType)
{
case "N":
return new ONetCourse();
case "J":
return new OJavaCourse();
default:
return null;
}
}
}
四方帮派定义了工厂方法模式
“这种模式定义了一个用于创建对象的接口,但是让子类决定要实例化哪个类。工厂方法允许类将实例化推迟到子类“。
现在定义是不言自明的。
第6天
时间向托马斯展示最终演示。
现在最终的UI代码将会是这样的
在线课程用户界面
AbstractCourseFactory objFactory = new OnlineCourseFactory();
AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration
企业课程用户界面
AbstractCourseFactory objFactory = new CorporateCourseFactory();
AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration
方法优点4
- 如果将来在Programmer24X7中引入一个新的课程组(例如离线课程),一个新的工厂将从AbstractCourse获得,该工具将封装所有与之相关的具体课程(例如离线Java课程,离线.NET课程)的创建组。很简单
这就是工厂方法模式。最后,托马斯似乎很高兴,因为他的所有要求都很满意,而且亚历山大也很开心,因为现在他已经成为工厂方法模式的冠军
其他方法和想法
- 母工厂是否必须总是抽象?
这个问题的答案是否。如果需要,我们可以使其非抽象,并将默认实现添加到GetCourse方法使其成为虚拟。 - 在工厂中是否需要开关?
不,我们可以用.NET中的Dictionary替换开关循环。 - 从二级工厂继承是可能的吗?
是绝对的,这就是工厂方法的工作原理。最初,我们使用了AbstractCourseFactory,其默认实现为GetCourse方法,后来将被OnlineCourseFactory扩展,为GetCourse方法添加了自己的实现,后者又可以是一个虚拟方法。所以后来说当在Programmer24X7中引入一个新的OnlineAdvanceCourse时,OnlineCourseFactory可以轻松扩展。 - 在Factory Method Pattern的情况下使用MultiLevel继承的优点是什么?
那么请考虑以下情况。- 我们有AbstractCourseFactory和OnlineCourseFactory。
- OnlineCourseFactory覆盖GetCourse方法,用于定义Java和.net的在线课程。
- 现在让我们假设新课程在一年之后添加到在线课程,我们甚至没有兴趣打开OnlineCourseFactory。
- OnlineCourseFactoryVersion2将会介绍。
- 现在,如果我们从AbstractCourseFactory派生OnlineAdvanceCourseFactory,我们应该定义所有以前的课程,如Java和.NET以及新的一个生成的冗余代码。
- 除了我们能做的事情之外,我们将会帮助字典存储所有可用的课程,并在每个级别上添加课程。
我们来看一下代码片段。
public abstract class AbstractCourseFactory
{
protected Dictionary<string, AbstractCourse> ObjCourses;
public AbstractCourseFactory()
{
ObjCourses = new Dictionary<string, AbstractCourse>();
}
}
public class OnlineCourseFactoryVersion2 : OnlineCourseFactory
{
public OnlineCourseFactoryVersion2()
{
ObjCourses.Add("V", new OVCourse());
}
}
注意:所以在工厂方法模式中使用字典总是被认为是一种很好的方法。
所以这完成了我的第一篇关于工厂模式的文章...希望你喜欢它...请不要忘记留下你的意见....你的积极和消极的意见将鼓励我写得更好...谢谢! !
源代码下载
点击以下链接以获取完整的源代码
对于与其他设计模式和.NET相关的任何培训,您可以通过SukeshMarla@Gmail.com或www.sukesh-marla.com与我联系
点击并进入这里,以获得更多关于.NET和C#学习的东西
从无工厂到工厂方法
![](https://www.codeproject.com/script/Membership/ProfileImages/%7Ba3923c88-65fa-4bc6-911a-227339669a4c%7D.jpg)
4.87(150票) |
|
工厂方法模式 - 从新关键字中减轻
介绍
当我们听到“设计模式”这个词时,我们头脑中的第一个问题是“什么是设计模式”?
设计模式是针对软件开发中经常出现的问题的可重复使用和记录的解决方案。
四人帮(GOF)将“设计模式”分为3类
- 创力
- 结构
- 行为的
当我开始学习设计模式时,我发现Factory方法是一个非常有趣的模式。它是最有争议和最困惑的创作模式之一。人们在理解这种模式时有很多混乱。
首先让我让大家清楚,没有什么像工厂模式(根据GOF设计模式列表),GOF有一些叫做工厂方法模式的东西。(在这个阶段的后面我们会碰到这两个术语)
在本文中,我将介绍两个虚构人物亚历山大(.NET开发人员)和托马斯(IT研究所首席执行官Programmer24X7)。
故事从托马斯接触亚历山大的那天开始,并要求他在他的内部项目“课程管理系统”中担任建筑师的角色。我们将看到亚历山大如何日益发展自己对工厂方法模式的了解,以及他如何最终提出一个很好的解决方案。
在开始阅读这篇文章之前,从我身边提供一些小小的建议,除了你以外,还要保留一些零食,因为这将是一个疲惫的6天的故事。基本上我正在努力玩你的耐心。别担心只是在开玩笑。它会很有趣,你会喜欢阅读这篇文章,在这篇文章的最后,你可以自豪地说“我知道工厂方法模式”。
所以放松一下,让我们开始学习工厂方法模式
指数
- 第一天 - 亚历山大如何开始? - 方法1 - 无工厂方法
- 第二天 - 亚历山大·继续吗? - 方法2 - 简单的工厂方法
- 第3天 - 方法3 - 多个简单的工厂方法
- 第4天 - 关于多个简单的工厂方法的讨论
- 第4天 - 夜晚 - 对象噩梦
- 第5天 - 方法4 - 工厂方法方法
- 第6天 - 最终演示
- 其他方法和想法
- 源代码下载
第1天
亚历山大(我们的.NET开发人员)收集了Thomas(我们的Programmer24X7 CEO)的要求。他的主要要求之一是建立一个将管理Programmer24X7(技术学院)提供的在线课程的模块。
亚历山大怎么样?
我)系统亚历山大将要开发课程管理系统,所以第一个合乎逻辑的步骤就是开始创建课程库。
II)下一步将创建课程实例并构建UI - 用户界面。以下是每个程序员认为最明显的代码,甚至亚历山大也是如此。
方法1 - 无工厂方法
AbstractCourse objCourse = null; switch(StrUserInput) { case "N": objCourse = new NetCourse(); break; case "J": objCourse = new JavaCourse(); break; } objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); //Display objCourse.CourseName and objCourse.CourseDuration
最后一步 - 示范
自从模块准备好以来,亚历山大对托马斯也是一样的,托马斯对建筑的感觉很好。亚历山大的努力得到了很好的赞赏,但这一切都没有结束。然后,他接受了下一个逻辑层面的要求,他就应用程序分享了他的进一步计划。他说,
- 他计划添加新的在线课程,如C ++,VC ++等,并希望在将来停止几门课程。
- 将来在Programmer24X7离线课程将要进行,所以确保使一切可重用。
托马斯要求亚历山大根据这个先进的范围进行更改。那么亚历山大呢就是一个大惊喜
这是像煎锅一样,但进入亚历山大的火情。
“添加新课程意味着”,打开现有的UI代码现有逻辑(添加更多的开关案例,并在将来删除一些现有的案例)。
考虑建筑师的情况,建筑施工结束后,被要求在1楼和2楼之间再增加一层,建筑物不会崩溃。
方法问题1
- 当课程库修改时,SOLID原则OCP(Open Closed Principle)将被违反。(OCP说,软件实体(类,模块,功能等)应该是开放的扩展,但关闭修改)
- 在另一个用户界面中重复使用相同的(课程创建)逻辑是不可能的。
亚历山大学什么?
亚历山大认识到软件开发的一个重要内容,并学到了一个很大的教训:“变革是开发的重要组成部分,系统应该能够轻松适应这种变化,而不需要修改现有的测试部分。”
不是很有趣,改变系统,但不要改变代码。好吧,我们来看看我们如何做到这一点。
第二天
亚历山大·亚历山大·
亚历山大第二天清晨起床。咖啡在他手中,但心中仍在考虑手头的问题。他从黑暗的天空找到正确的星星是非常困难的,但是最终他设法找到了月球,而那里就是方法2。
|
|
方法2 - 简单的工厂方法
在第一种方法中,UI正在创建课程对象。
![]() |
现在,如果将对象创建的力量从UI中取出并将其赋予其他人,那将是如何。这里别人叫Simple Factory类。 |
什么是简单工厂?
Simple Factory是一个具有公共静态方法的类,它将根据所获取的输入实际执行对象创建任务。
public class CourseFactory { public static AbstractCourse CreateCourse(string ScheduleType) { AbstractCourse objCourse = null; switch(ScheduleType) { case "N": objCourse = new NetCourse(); break; case "J": objCourse = new JavaCourse(); break; //Add more case conditions here for VC++ and C++ } objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); return objCourse; } }
UI
AbstractCourse objCourse = CourseFactory.CreateCourse(StrUserInput); //Display objCourse.CourseName and objCourse.CourseDuration
方法的优点2
- 每当引入新课程时,更改的是工厂不是客户端代码。
- 由于工厂是类,任何人都可以使用它有权访问。简而言之,课程逻辑现在可以重复使用。
最后一步 - 示范
晚些时候,亚历山大达到了Programmer24X7办公室来展示这一修订的架构。但在亚历山大开始表达自己的焦虑之前,又出现了一个令人惊讶的要求。托马斯说:“我认为,如果我们为企业时间表增加一个UI,那会更好。原因是,现在我的企业培训计数增加了很多,所以我变得不可能管理。“
I)现在我们应该做的第一件事是改变课程图书馆(因为我们需要添加公司课程)。
II)为我们的Simple Factory类添加更多的案例条件。
public class CourseFactory { public static AbstractCourse CreateCourse(string ScheduleType) { AbstractCourse objCourse = null; switch(ScheduleType) { case "CN": objCourse = new CNetCourse(); break; case "CJ": objCourse = new CJavaCourse(); break; case "CB": objCourse = new CBICourse(); break; case "OJ": objCourse = new OJavaCourse(); break; case "ON": objCourse = new ONetCourse(); break; } objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); return objCourse; } }
方法问题2
使用简单工厂方法可以很容易地覆盖新的要求,那么呢?
- 尽管所有类都源自抽象课程,但在单个简单工厂中添加了五种情况违反SOLID原理SRP - 单一责任原则。(SRP说一个类应该只有一个原因要改变。)
这里Factory类将被更改- 每当新的公司课程介绍或修改。
- 每当新的在线课程介绍或修改。
所以这个Simple Factory解决方案在当前的问题环境中不会运行。
第3天
我们列出我们的所有要求。
- 我们需要工厂的在线课程
- 我们需要企业课程的工厂
- 我们不想为两个模块创建单个工厂。
- 如何使用多个简单的工厂。
- OnlineCourseFactory
- CorporateCourseFactory
方法3 - 多个简单的工厂方法
在这种方法中,我们将有多个简单的工厂,每个工厂都有一个静态方法,它将根据它获得的输入创建一个实例。
![](https://www.codeproject.com/images/arrow-up-16.png)
public class CorporateCourseFactory { public static AbstractCourse CreateCourse(string ScheduleType) { AbstractCourse objCourse = null; switch(ScheduleType) { case "N": objCourse = new CNetCourse(); break; case "J": objCourse = new CJavaCourse(); break; case "B": objCourse = new CBICourse(); break; } objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); return objCourse; } } public class OnlineCourseFactory { public static AbstractCourse CreateCourse(string ScheduleType) { AbstractCourse objCourse = null; switch(ScheduleType) { case "N": objCourse = new ONetCourse(); break; case "J": objCourse = new OJavaCourse(); break; } objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); return objCourse; } }
在线课程用户界面
AbstractCourse objCourse = OnlineCourseFactory.CreateCourse(StrUserInput); //Display objCourse.CourseName and objCourse.CourseDuration
企业课程用户界面
AbstractCourse objCourse = CorporateCourseFactory.CreateCourse(StrUserInput); //Display objCourse.CourseName and objCourse.CourseDuration
一切解决问题解决了。
第4天
亚历山大第二天到达Programmer24X7并向Thomas解释了托马斯的回答是什么?是好是坏?
在研究建筑之后,我们进行了大量讨论的小脚本。
托马斯:对不起,亚历山大,但我不认为这个解决方案会奏效。
亚历山大:为什么先生
托马斯:看到,对于每个课程组,都有一个单独的工厂。(OnlineCourseFactory,CoporateCourseFactory)。
但是,您将如何对每个工厂进行控制。我的意思是如何确保每个工厂正确地创建对象,例如,如何确保每个工厂遵循公司标准,并在返回对象之前创建课程材料和计划。
有可能在未来有一家工厂表示,OfflineCourseFactory被添加用于管理离线课程,并且不知不觉中它违反了公司标准,并以自己的方式创建课程材料。
亚历山大:你是对的先生。让我考虑一个完整的证明和最终的解决方案,给我一天。
托马斯:没有问题亚历山大 祝你今天愉快。
方法问题3
- 每个工厂都是独立的。定义工厂没有严格的规定。在这种方式下,每个工厂都可以有自己的结构和标准。
第4天 - 晚上
我们列出我们的所有要求。
- 我们需要工厂的在线课程
- 我们需要企业课程的工厂
- 我们不想为两个模块创建单个工厂。
- 应该有一些规则,如何界定每个人都应该遵循的工厂。
- 如果我们使用方法3的组合(即每当需要创建新工厂)
加上继承或组合时,它将如何。
- 是时候睡觉了。
第5天
亚历山大昨晚在说什么?
- 将所有常见功能放在一个地方(类),并在所有工厂中重用它们。
我们称之为“ReusbaleClass”用于讨论目的。我们需要可重用性 -
我们可以通过两种方法来实现。- 继承 - 从ReusbaleClass派生所有工厂 - >调用解决方案1
- 与组合 - 所有工厂将有一个类型为ReusbaleClass的成员 - >调用它解决方案2
- 让工厂覆盖ReusbaleClass中定义的某些功能(每个工厂都不同)。
- 我们需要覆盖意味着解决方案1将适合完美。
方法4 - 工厂方法方法
简而言之,我们需要一个这样的类,它将执行所有常见任务并暴露虚拟或抽象函数。
所以让我们创建一个AbstractCourseFactory,它将使用一个额外的可覆盖(虚拟或抽象)方法来封装通用的功能,然后重新创建我们的OnlineCourseFactory和CorporateCourseFactory。
public abstract class AbstractCourseFactory { public AbstractCourse CreateCourse(string ScheduleType) { AbstractCourse objCourse = this.GetCourse(ScheduleType); objCourse.CreateCourseMaterial(); objCourse.CreateSchedule(); return objCourse; } public abstract AbstractCourse GetCourse(string ScheduleType); }
请注意GetCourse方法是抽象的
现在,每个(每个工厂)都将容易地覆盖这个GetCourse方法。
![](https://www.codeproject.com/images/arrow-up-16.png)
public class CorporateCourseFactory:AbstractCourseFactory { public override AbstractCourse GetCourse(string ScheduleType) { switch(ScheduleType) { case "N": return new CNetCourse(); case "J": return new CJavaCourse(); default: return null; } } } public class OnlineCourseFactory : AbstractCourseFactory { public override AbstractCourse GetCourse(string ScheduleType) { switch(ScheduleType) { case "N": return new ONetCourse(); case "J": return new OJavaCourse(); default: return null; } } }
四方帮派定义了工厂方法模式
“这种模式定义了一个用于创建对象的接口,但是让子类决定要实例化哪个类。工厂方法允许类将实例化推迟到子类“。
现在定义是不言自明的。
第6天
时间向托马斯展示最终演示。
现在最终的UI代码将会是这样的
在线课程用户界面
AbstractCourseFactory objFactory = new OnlineCourseFactory(); AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput); //Display objCourse.CourseName and objCourse.CourseDuration
企业课程用户界面
AbstractCourseFactory objFactory = new CorporateCourseFactory(); AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput); //Display objCourse.CourseName and objCourse.CourseDuration
方法优点4
- 如果将来在Programmer24X7中引入一个新的课程组(例如离线课程),一个新的工厂将从AbstractCourse获得,该工具将封装所有与之相关的具体课程(例如离线Java课程,离线.NET课程)的创建组。很简单
这就是工厂方法模式。最后,托马斯似乎很高兴,因为他的所有要求都很满意,而且亚历山大也很开心,因为现在他已经成为工厂方法模式的冠军
其他方法和想法
- 母工厂是否必须总是抽象?
这个问题的答案是否。如果需要,我们可以使其非抽象,并将默认实现添加到GetCourse方法使其成为虚拟。 - 在工厂中是否需要开关?
不,我们可以用.NET中的Dictionary替换开关循环。 - 从二级工厂继承是可能的吗?
是绝对的,这就是工厂方法的工作原理。最初,我们使用了AbstractCourseFactory,其默认实现为GetCourse方法,后来将被OnlineCourseFactory扩展,为GetCourse方法添加了自己的实现,后者又可以是一个虚拟方法。所以后来说当在Programmer24X7中引入一个新的OnlineAdvanceCourse时,OnlineCourseFactory可以轻松扩展。 - 在Factory Method Pattern的情况下使用MultiLevel继承的优点是什么?
那么请考虑以下情况。- 我们有AbstractCourseFactory和OnlineCourseFactory。
- OnlineCourseFactory覆盖GetCourse方法,用于定义Java和.net的在线课程。
- 现在让我们假设新课程在一年之后添加到在线课程,我们甚至没有兴趣打开OnlineCourseFactory。
- OnlineCourseFactoryVersion2将会介绍。
- 现在,如果我们从AbstractCourseFactory派生OnlineAdvanceCourseFactory,我们应该定义所有以前的课程,如Java和.NET以及新的一个生成的冗余代码。
- 除了我们能做的事情之外,我们将会帮助字典存储所有可用的课程,并在每个级别上添加课程。
我们来看一下代码片段。
public abstract class AbstractCourseFactory { protected Dictionary<string, AbstractCourse> ObjCourses; public AbstractCourseFactory() { ObjCourses = new Dictionary<string, AbstractCourse>(); } } public class OnlineCourseFactoryVersion2 : OnlineCourseFactory { public OnlineCourseFactoryVersion2() { ObjCourses.Add("V", new OVCourse()); } }
注意:所以在工厂方法模式中使用字典总是被认为是一种很好的方法。
所以这完成了我的第一篇关于工厂模式的文章...希望你喜欢它...请不要忘记留下你的意见....你的积极和消极的意见将鼓励我写得更好...谢谢! !
源代码下载
点击以下链接以获取完整的源代码
对于与其他设计模式和.NET相关的任何培训,您可以通过SukeshMarla@Gmail.com或www.sukesh-marla.com与我联系
点击并进入这里,以获得更多关于.NET和C#学习的东西
来源:https://www.codeproject.com/Articles/492900/From-No-Factory-to-Factory-Method