Образец фабричного метода нарушает принцип Open / Closed? - PullRequest
8 голосов
/ 04 марта 2010

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

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

Разве оба из них не нарушают Open / Closed?

Ответы [ 3 ]

5 голосов
/ 24 июня 2014

Фабричный образец по своей сути не является нарушителем 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 в этом случае является Pattern Decorator . Постоянное украшение Complex возможностью создавать новые варианты Complex соответствует OCP, поскольку Complex не изменяется, а расширяется за счет добавления новых функций.

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

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

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

4 голосов
/ 04 марта 2010

Нет, это не нарушает принцип Open / Closed.

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

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

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

2 голосов
/ 04 марта 2010

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

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

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

...