Answers:
常规的面向对象的知识是避免使用if
语句,而将其替换为抽象类的子类中的重写方法的动态分配。到现在为止还挺好。
但是工厂模式的重点是减轻您不必了解各个子类的麻烦,并且只使用抽象的超类。这样的想法是,工厂比您更了解要实例化哪个特定类,并且您最好只使用超类发布的方法。这通常是真实的并且是有价值的模式。
因此,编写工厂类无法放弃这些if
语句。这将把选择特定类的负担转移给调用者,这正是该模式应避免的事情。并非所有原理都是绝对的(实际上,没有原理是绝对的),并且如果您使用此模式,您将假定从中受益大于不使用if
。
if
。有关如何实现此目标的简单示例,请参见@BЈовић的答案。不赞成投票。
该示例可能使用条件语句,因为它是最简单的。一个更复杂的实现可能使用映射或配置,或者(如果您真的很想想)使用某种类型的注册表可以在其中注册自己的注册表。但是,如果类的数量很少且不经常更改,则使用条件语句没有任何问题。
严格说来,将来扩展条件以增加对新子类的支持实际上将违反开放/封闭原则。“正确”的解决方案是使用相同的界面创建一个新工厂。就是说,遵守O / C原则应始终与其他设计原则(如KISS和YAGNI)权衡。
也就是说,显示的代码显然是示例代码,旨在显示工厂的概念,仅此而已。例如,像示例一样,返回null确实是一种不好的风格,但是更复杂的错误处理只会掩盖这一点。示例代码不是生产质量代码,您不应期望任何代码。
模式本身不违反开放/封闭原则(OCP)。但是,如果我们错误地使用该模式,则会违反OCP。
这个问题的简单答案如下:
在提供的示例中,基本功能支持三种形状:圆形,矩形和正方形。假设您将来需要支持Triangle,Pentagon和Hexagon。要做到这一点而又不违反OCP,您必须创建一个额外的工厂来支持您的新形状(称为AdvancedShapeFactory
),然后使用AbstractFactory决定您需要创建哪个工厂才能创建所需的形状。
如果您在谈论抽象工厂模式,那么决策通常不在工厂本身中,而在应用程序代码中。该代码选择要实例化的具体工厂,并传递给将使用该工厂生产的对象的客户端代码。请在此处查看Java示例的结尾:https : //en.wikipedia.org/wiki/Abstract_factory_pattern
决策不一定意味着if
陈述。它可以从配置文件中读取具体的Factory类型,从映射结构中派生出来,等等。
如果您考虑使用此工厂在类级别进行“打开-关闭”操作,则在系统中创建其他“打开-关闭”类,例如,如果您有其他采用一个Shape并计算面积的类(典型示例),则该类为“打开关闭”,因为它可以不经修改就为新型形状计算面积。然后,您有另一个绘制形状的类,另一个具有N个形状并返回较大形状的类,您通常可以认为系统中处理形状的其他类是Open-Close(至少与形状有关)。从设计的角度来看,工厂使系统的其余部分处于“开-关”状态,而偏离工厂本身的方向是“不开/关”。
当然,您也可以通过某种动态加载使此工厂开-关,并且整个系统可以是开-关(例如,您可以在类路径中添加一些罐子来添加新形状)。您需要评估这种额外的复杂性是否值得,具体取决于您所构建的系统,并非所有系统都需要可插拔功能,并且并非所有系统都需要完全打开/关闭。
这完全取决于您如何实施。您可以std::map
用来保存指向创建对象的函数的函数指针。这样就不会违反打开/关闭原理。或开关/外壳。
无论如何,如果您不喜欢工厂模式,则可以始终使用依赖项注入。