Нарушает ли паттерн Factory Method принцип Open / Closed?

Нарушает ли шаблон Factory Method (не путать с шаблонами Factory или Abstract Factory) Принцип открытости / закрытости?

Обновление: чтобы уточнить, я имею в виду сценарий, в котором конкретный класс имеет статические фабричные методы. Например (это со страницы Википедии на 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) {
       //...
    }
}

Разве частный конструктор не предотвращает создание подкласса, то есть расширение класса?

Разве класс не нужно было бы модифицировать для поддержки новых фабричных методов? Например, если класс изначально имел только fromCartesian, а позже был необходим fromPolar, разве не нужно было изменять класс для поддержки этого?

Не оба ли из них нарушают открытый / закрытый?


person Todd Ropog    schedule 04.03.2010    source источник
comment
Я хотел бы знать, что вы думаете об этом, прежде чем я отвечу. Ваш ответ заставит меня почувствовать, что вы ищете ответ. В противном случае это похоже на то, что вы отдаете свою работу на аутсорсинг SO.   -  person amit    schedule 04.03.2010
comment
Извините, планировал добавить комментарий, но отвлекся на работу. :) Думаю, это нарушает. Пожалуйста, поправьте меня, если я ошибаюсь, но FMP требует частного конструктора, а частный конструктор запрещает расширение. Кроме того, не нужно ли модифицировать класс для поддержки альтернативных реализаций? Я думаю о ситуации, когда у класса есть статические фабричные методы. Может, это только одна разновидность FMP?   -  person Todd Ropog    schedule 04.03.2010
comment
Если это дочерний класс, вы можете переопределить метод или использовать super () (при условии, что Java). Вам лучше не иметь статических методов и иметь один единственный метод, который принимает параметры, чтобы выбрать, с помощью оператора switch или чтения в предоставленном файле конфигурации.   -  person Brian T Hannan    schedule 04.03.2010
comment
Разве оператор switch по-прежнему не требует изменения класса? А как насчет проблемы с закрытым конструктором, препятствующим расширению?   -  person Todd Ropog    schedule 04.03.2010
comment
Код Википедии, который вы цитируете, на самом деле не является классическим шаблоном Factory Method. Это похоже, но, на мой взгляд, это не одно и то же. Вы бы не использовали подобный код в ситуации, требующей фабричного метода.   -  person noah    schedule 04.03.2010
comment
Итак, основная проблема может заключаться в том, что то, что я считал разновидностью Factory Method, на самом деле не так. Согласны ли вы, что то, что представлено выше, нарушает принцип открытого / закрытого?   -  person Todd Ropog    schedule 05.03.2010
comment
Этот конкретный код на самом деле не так, потому что такие вещи, как числа, как правило, являются особым случаем, и способы их создания не являются чем-то, что ваши требования будут требовать для настройки. Но какой другой класс (содержащий бизнес-логику, которая может измениться), у которого есть частный конструктор и статические фабричные методы? да.   -  person noah    schedule 05.03.2010
comment
Различия между абстрактным фабричным шаблоном и фабричным методом Пример здесь ни то, ни другое.   -  person jaco0646    schedule 31.10.2018


Ответы (3)


Нет, это нисколько не нарушает принципа «открыто / закрыто».

Открытый / Закрытый означает, что вы можете изменить способ работы системы, не изменяя уже существующий код. Вы можете расширить код и использовать его по-разному, но старый код все еще работает и не требует повторного тестирования.

Шаблон Factory Method создаст объект другого типа на основе заданных параметров. Заводской метод действительно хорошо работает с принципом «открыто / закрыто», если все сделано правильно. Однако, если вы создаете новый класс, а затем хотите, чтобы фабричный метод создавал новый объект этого типа, вам придется изменить фабричный метод.

Хотя, если у вас был какой-то файл конфигурации или что-то в этом роде, которое читается фабричным методом, вам не нужно было бы изменять фабричный метод ... только файл конфигурации, который затем определяет, какой объект будет создан Заводской метод.

person Brian T Hannan    schedule 04.03.2010

Шаблон Factory не является нарушителем 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 расширяется, но не изменяется.

Другой дружественной OCP альтернативы изменению Complex в этом случае является Шаблон декоратора. Постоянное украшение Complex возможностью создания новых вариантов Complex уважает OCP, потому что Complex не изменяется, а расширяется за счет добавления новых функций.

Третьей альтернативой может быть изменение структуры Complex так, чтобы его вычисление осуществлялось композицией. Это откроет вам возможность использовать шаблон стратегии, чтобы различать различные варианты поведения Complex .

Особенность шаблона Factory в том, что он помогает контекстному коду уважать OCP. Чтобы оставаться на правой стороне OCP со своими Factory, но ваши коллеги, скорее всего, взглянут на граф объектов, усомнятся в целесообразности наличия графа объектов над одной Factory и упростят его до одной Factory, что вернет вас к первому примеру.

В таких случаях вместо того, чтобы пытаться изменить вашу реализацию шаблона Factory для соблюдения SOLID, подумайте, почему вы его используете вообще.

person 8bitjunkie    schedule 24.06.2014

Неа. Из вашей ссылки в Википедии:

программные объекты (классы, модули, функции и т. д.) должны быть открыты для расширения, но закрыты для модификации

Переопределение фабричного метода - это расширение. Вы создаете новый класс. Вы не меняете существующий класс. Вы должны заменить (надеюсь, через конфигурацию вашего контейнера IoC) подкласс для оригинала.

person noah    schedule 04.03.2010