我一直在使用工厂方法创建模式一段时间。我刚刚被告知这个:
public static class ScheduleTypeFactory
{
public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)
{
IScheduleItem scheduleItem = null;
switch (scheduleType)
{
case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
{
scheduleItem = new VODScheduleItem();
break;
}
case ScheduleTypeEnum.BroadbandScheduleTypeID:
{
scheduleItem = new VODScheduleItem();
break;
}
case ScheduleTypeEnum.LinearCableScheduleTypeID:
{
scheduleItem = new LinearScheduleItem();
break;
}
case ScheduleTypeEnum.MobileLinearScheduleTypeID:
{
scheduleItem = new LinearScheduleItem();
break;
}
}
return scheduleItem;
}
}
不是我的“技术”主管的工厂方法创建模式,而没有告诉我为什么或给我她的解释。我很友好地要求解释,她告诉我她没有时间。我被告知要重命名它。如果我错了,那么毫无疑问我会接受我已经错误地实施了多年。这是你如何实现工厂方法创建模式?提前谢谢。
答案 0 :(得分:31)
我同意将该方法称为“工厂方法”,尽管该设计并非严格意义上的“工厂方法模式”。
这是一个关键点(来自维基百科):
... Factory方法允许类将实例化推迟到子类。“
由于您的类是静态的并且方法是静态的(因此是非虚拟的),因此不存在“延迟”。
从概念上讲,另请注意,此实现虽然提供了封装,但并未解除/延迟任何决策。
话虽如此,同样的维基百科文章确实将此架构呈现为“工厂方法模式”的变体。
摘要摘要:在我看来,这个代码段不是“工厂方法OO设计模式”的正确的实现,因为它不满足“类延迟实例化到子类”。虽然,我个人可以自由地将此解决方案称为“工厂方法”。
要使其成为真正的工厂方法模式,您需要允许子类重写该方法。即工厂类(ScheduleTypeFactory)需要是可扩展的(即非静态的),而GetScheduleItem需要是虚拟的。
答案 1 :(得分:29)
当然看起来像我的工厂模式。我认为你的实施没有任何问题。
工厂模式的本质是 “定义用于创建的界面 一个对象,但是让子类 决定实例化哪个类。该 工厂方法让课程推迟 实例化到子类。“
这正是你在做的事情。
作为旁注:一个好的经验法则是,每当有人告诉你某事并且不能或不愿意为他们的陈述提供理由时,他们很有可能完全没有资格作出陈述。
答案 2 :(得分:14)
是的,这是工厂模式。我唯一的评论是你无法为你没有专门处理的枚举值而无声地失败。这可能是预期的,但我喜欢将以下内容添加到像
这样的语句的末尾default:
throw new InvalidOperationException("Invalid Enum Value");
答案 3 :(得分:12)
您的代码片段是Head First Design Patterns中称为“简单工厂”的代码片段(第117页)
与Factory Method Pattern的主要区别在于 ConcreteCreator (比较右上角的图表),这是一个简单的类。
在“真实模式”中,工厂类是抽象的工厂类。所以,还有一个抽象层次。但是,对于许多用例,简单工厂就足够了。
简单工厂 Simple Factory http://yuml.me/7221a4c9 工厂方法模式 Factory Method Pattern http://yuml.me/3d22eb4e
答案 4 :(得分:8)
你的领导是正确的(对不起格式化,但这个答案需要一些,以便在主线之间看到表明领先是白痴):GOF都没有book and Head First这是一种工厂方法。
GoF:
“定义用于创建的界面 对象,但让子类决定 要实例化的类。厂 方法让一个类推迟 实例化到子类。“
在您的示例中,不是决定的子类。
这些年来你有没有错误地实现它?不,你刚刚没有实现工厂模式,但有时也称为“简单工厂模式”,可能已经完成了这项工作。
答案 5 :(得分:8)
我认为它传统上被称为简单的工厂模式,以区别于“真正的”Abstract Factory模式。可能是因为您没有遵守某种内部命名惯例。她真的应该解释一下自己。
答案 6 :(得分:5)
对我来说看起来像一个(基本)工厂......在许多工厂中,实现更复杂(可能涉及在运行时解析的类型),但这不是(AFAIK)的要求。我要添加的唯一其他批评是将案例结合起来,如果你不认识那种类型,就做一些更具戏剧性的事情......
答案 7 :(得分:5)
我很惊讶这么多人说这是工厂模式。 (所以很可能我认为这是错的,所以请让我知道。)
在我看来,你所拥有的只是设计的一部分。如果您从客户端调用它,它被称为“简单”工厂,但它并不是真正的设计模式。 (别误会我的意思,我一直这样做。)
工厂设计模式将声明您的工厂继承/实现抽象工厂/工厂接口。
然后,在需要使用工厂(客户端)的类中,将工厂类型设置为抽象/接口,创建具体工厂: 即 - > IFactory factory = new ConcreteFactory();
然后具体工厂将创建您的IScheduleItem(将其留给工厂以实际创建具体类型)。
最后,我认为重点是疏松耦合。虽然一个“简单”的工厂松散地将产品的结构与客户结合在一起,但它并没有使工厂脱钩。工厂模式也使工厂脱钩。
然后,它还早,我没有喝咖啡,而且我有一种讨厌的习惯,即发布绝对可怕的回答,错过了问题的全部内容。
答案 8 :(得分:4)
这是工厂模式,但它不一定是最易维护的变体。 更易于维护的变体会在ScheduleTypeEnum
值与IScheduleItem
的实际具体子类型之间维护某种全局映射 - 这样,您可以替换switch
语句查找地图。
为什么它更易于维护?因为子类作者可以在他们派生类的站点上向地图添加对,而不是GetScheduleItem()
工厂功能本身。因此,后者永远不需要更新;它不断更新。
在C ++中,您可以使用全局std::map
执行此操作 - 对于每个具体的子类,子类的作者添加一个虚拟全局变量,该变量实际上只是在其构造函数中注册类(通过添加到映射) ,在程序启动时运行。我确信在C#中有一种方便的方法可以做同样的事情。
(C ++大师Herb Sutter有entertaining description here,但它相当C ++重。)
答案 9 :(得分:4)
对我来说看起来像工厂模式。告诉你的技术主管,你没有时间解释她错的原因。
答案 10 :(得分:4)
嗯,维基百科说it is是一种工厂方法:
public class ImageReaderFactory
{
public static ImageReader getImageReader( InputStream is )
{
int imageType = figureOutImageType( is );
switch( imageType )
{
case ImageReaderFactory.GIF:
return new GifReader( is );
case ImageReaderFactory.JPEG:
return new JpegReader( is );
// etc.
}
}
}
答案 11 :(得分:2)
它确实是一个“工厂”,因为你有一个方法可以根据某种逻辑返回IScheduleItem
的特定实例;但是,鉴于您使用的是switch语句,它可能不是最佳实现或最易维护的。
答案 12 :(得分:0)
技术主管可能会想到的是,Factory模式是替换同一对象中的构造函数,而不是返回子类,或者可能只返回超类中的子类,而不是来自不相关的对象。这是错的,但这可能是想法。
维基百科列出您的模式作为一个例子表明它是正确的工厂模式。定义模式是为了提供通用解决方案的通用语言,所以很明显,如果维基百科以此为例,它就是通用语言的一部分。关于“工厂模式”在某种抽象意义上的含义的学术争论忽略了模式的重点。
答案 13 :(得分:0)
立即取回电源!只需从措辞中删除“类型”即可。 ScheduleFactory FTW。等等,这是'Scheduleles'或'ScheduleItems'的工厂吗?如果它是scheduleitems,那么工厂应该被称为'ScheduleItemFactory'。富有表现力!!!
答案 14 :(得分:0)
这是工厂方法模式,至少根据维基百科: http://en.wikipedia.org/wiki/Factory_method_pattern
答案 15 :(得分:0)
对我来说看起来像一个基本的工厂模式。我很想知道为什么你的技术主管不认为这是一种模式。
我也很失望她不会花时间解释事情。在团队成为技术领导之前,花点时间来解释你的决定是很有意义的。
答案 16 :(得分:0)
我从模式和练习课中学到的工厂模式的最简单的解释是,如果你依赖另一个类来创建你的类的实例,那么你就是在使用工厂模式。
当然,通常你想通过使你的类抽象或接口来添加一个间接层。
这是非常简化的视图,但无论哪种方式,您都在使用工厂模式。
答案 17 :(得分:0)
答案 18 :(得分:0)
您的技术人员正确地重命名该方法:
public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)
该方法的作用不是为了获得某些东西,而是创建的东西。 你如何决定应该创建哪个scheduleType?似乎逻辑应该 封装不是类型的开关。
为什么班上的静态呢?你在哪里使用它?
public class ScheduleTypeFactory
{
public static IScheduleItem createScheduleFrom(ScheduleTypeEnum scheduleType)
{
switch (scheduleType)
{
case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
case ScheduleTypeEnum.BroadbandScheduleTypeID:
return new VODScheduleItem();
case ScheduleTypeEnum.LinearCableScheduleTypeID:
case ScheduleTypeEnum.MobileLinearScheduleTypeID:
return new LinearScheduleItem();
}
raise InvalidSchedule;
}
}
答案 19 :(得分:-1)
这是一本教科书工厂模式。
有些文章称它为简单工厂模型,但我从未见过“简单”意味着什么标准。
在我的实践中,工厂模式是对应于所需界面的具体类的任何智能创建。
但是为什么要在命名方法上与你的技术领先。重命名,继续你的生活。