首页 文章

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

提问于
浏览
8

Factory Method pattern(不要与Factory或Abstract Factory模式混淆)是否违反了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,那么是否必须修改该类才能支持此类?

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

3 回答

  • 2

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

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

    Factory Method模式将根据指定的参数创建不同类型的对象 . 如果正确完成,工厂方法实际上适用于打开/关闭原则 . 但是,如果创建新类,然后希望工厂方法创建该类型的新对象,则必须更改工厂方法 .

    虽然,如果您有某种配置文件或工厂方法读取的那种配置文件,那么您不必更改工厂方法...只需配置文件,然后指定将由哪个对象创建工厂方法 .

  • 4

    工厂模式本身并不违反OCP .

    这取决于 how 你进一步采取 Complex 的行为 .

    如果 Complex 需要支持生成新类型的 Complex 对象,并且您选择通过添加新的 Complex 来修改 Complex 方法以添加它们,那么这意味着 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 的友好替代方案是Decorator pattern . 通过创建 Complex 的新变体的能力不断装饰 Complex 尊重OCP,因为 Complex 未被修改,但通过使用新功能包装来扩展 .

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

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

    在这种情况下,不要试图弯曲Factory模式的实现以尊重SOLID原则,而应考虑为什么要使用它 .

  • 5

    不 . 从您的维基百科链接:

    软件实体(类,模块,函数等)应该是可以扩展的,但是关闭以进行修改

    覆盖工厂方法是扩展 . 你正在创建一个新类 . 您不会更改现有的类 . 您必须替换(通过配置您的IoC容器希望)原始的子类 .

相关问题