Factory Method pattern(不要与工厂或抽象工厂模式混淆)是否违反了Open/Closed principle?
更新: 为了澄清,我指的是具体类具有静态工厂方法的场景。例如(这是来自FMP上的维基百科页面):
class Complex
{
public static Complex fromCartesian(double real, double imag) {
return new Complex(real, imag);
}
public static Complex fromPolar(double modulus, double angle) {
return new Complex(modulus * cos(angle), modulus * sin(angle));
}
private Complex(double a, double b) {
//...
}
}
私有构造函数是否阻止该类被子类化,即扩展?
是否不必修改课程以支持新的工厂方法?例如,如果该类最初只需要来自Caresian,后来需要使用thePolar,那么是否必须修改该类才能支持此类?
这两种情况都不违反开放/封闭吗?
答案 0 :(得分:5)
工厂模式本身并不是OCP的违规者。
这取决于如何您进一步采取Complex
的行为。
如果需要Complex
来支持新类型的Complex
对象的生成,并且您选择通过添加新的Complex
方法来修改fromX
,则会添加这些方法来支持它们,这意味着Complex
成为OCP的违规者,因为必须重新打开Complex
进行修改:
class Complex
{
public static Complex fromCartesian(double real, double imag) {
return new Complex(real, imag);
}
public static Complex fromPolar(double modulus, double angle) {
return new Complex(modulus * cos(angle), modulus * sin(angle));
}
//class opened for modification
public static Complex fromOtherMeans(String x , String y) {
return new Complex(x, y);
}
}
您可以将此问题下推到某种文本文件或属性文件中,以免自己不得不更改java类,但它并不能阻止您在此区域编写额外的逻辑解决方案,以支持新类型的Complex
。
根据您设计中Complex
的用法(各种类型有何不同?您如何使用它们?),有一些替代方案可能适用。
一个这样的OCP友好替代方案是将Complex
子类化以提供其他工厂方法。子类是Complex
如何扩展但未修改的最简单说明。
在这种情况下,改变Complex
的另一个OCP友好替代方案是Decorator pattern。通过创建Complex
的新变体来持续装饰Complex
尊重OCP,因为Complex
未被修改,但通过使用新功能包装它而得到扩展。
第三种选择可能是改变Complex
的结构,以便其计算由合成提供。这将使您有机会使用Strategy pattern来区分Complex
的不同行为。
关于Factory模式的事情是它有助于上下文代码尊重OCP。有人可能会采用上述技巧之一,以便使用他们的Factory类保持在OCP的右侧,但是你的同事可能会看一下对象图,质疑拥有对象图的智慧在一个工厂,并将其简化为一个工厂,它将带您回到第一个例子。
在这种情况下,不要试图弯曲您的工厂模式的实现以尊重SOLID原则,而应考虑为什么您一直使用它。
答案 1 :(得分:4)
不,它根本不违反开放/封闭原则。
打开/关闭意味着您可以修改系统的工作方式,而无需修改已存在的代码。您可以扩展代码并以不同的方式使用它,但旧代码仍然很有用,不需要重新测试。
Factory Method模式将根据指定的参数创建不同类型的对象。如果正确完成,工厂方法实际上适用于打开/关闭原则。但是,如果您创建一个新类,然后希望工厂方法创建该类型的新对象,则必须更改工厂方法。
虽然,如果您有某种配置文件或工厂方法读取的那种配置文件,那么您就不必更改工厂方法...只需配置文件然后指定哪个对象将由工厂方法创建。
答案 2 :(得分:2)
不。从您的维基百科链接:
软件实体(类,模块,函数等)应该是可以扩展的,但是关闭以进行修改
覆盖工厂方法是扩展名。你正在创建一个新类。您不会更改现有的类。您必须替换(通过配置您的IoC容器)原始的子类。