工厂方法模式是否违反开放/封闭原则?

Tod*_*pog 8 design-patterns factory-method 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) {
       //...
    }
}
Run Code Online (Sandbox Code Playgroud)

私有构造函数不会阻止类被子类化,即扩展吗?

是否必须修改类以支持新的工厂方法?例如,如果该类最初只有来自Caresian,后来需要来自thePolar,那么是否必须修改该类才能支持此类?

这两个都不违反开放/封闭吗?

Bri*_*nan 6

不,它根本不违反开放/封闭原则。

开放/封闭意味着您可以修改系统的工作方式,而无需修改已存在的代码。您可以扩展代码并以不同方式使用它,但旧代码仍然完好无损,不需要重新测试。

工厂方法模式将根据指定的参数创建不同类型的对象。如果正确完成,工厂方法实际上可以很好地与开/关原则配合使用。但是,如果您创建一个新类,然后希望工厂方法创建该类型的新对象,则必须更改工厂方法。

虽然,如果您有某种配置文件或工厂方法读取的那种类型的东西,那么您就不必更改工厂方法......只是配置文件然后指示将创建什么对象工厂方法。


8bi*_*kie 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以将此问题下载到某种文本文件或属性文件中,以免自己不得不更改java类,但这并不妨碍您必须在解决方案的这个区域中编写额外的逻辑支持新类型Complex.

根据Complex您设计中的用法(各种类型有何不同?您如何使用它们?),有一些替代选项可能适用.

一个这样的OCP友好替代方案是子类Complex以提供额外的工厂方法.子类是如何Complex扩展但未修改的最简单的说明.

在这种情况下,另一种OCP友好的替代方案Complex装饰器模式.Complex通过创建Complex符合OCP的新变体的能力不断进行装饰,因为Complex它没有被修改,而是通过用新功能包装来扩展.

第三种选择可能是改变结构Complex,使其计算由组合提供.这将使您有机会使用策略模式来区分不同的行为Complex.

关于Factory模式的事情是它有助于上下文代码尊重OCP.有人可能会采用上述技术之一,以便在他们的Factory类中保持在OCP的右侧,但是你的同事可能会看一下对象图,质疑在一个工厂上有一个对象图的智慧,并将其简化为一个工厂,它将带您回到第一个示例.

在这种情况下,而不是试图弯曲你的工厂模式,以尊重的实施SOLID原则,考虑为什么你使用它的全部.