Почему фабричный метод не нужен, когда «создание экземпляра происходит в операции, которую подклассы могут легко переопределить»? - PullRequest
1 голос
/ 11 июня 2019

Из шаблонов проектирования Гаммы и др.,

Фабричный метод делает дизайн более настраиваемым и лишь немного более сложным. Другие шаблоны проектирования требуют новых классов , тогда как Factory Method требует только новой операции.Люди часто используют Factory Method в качестве стандартного способа создания объектов, но в этом нет необходимости , когда созданный экземпляр класса никогда не меняется или , когда создание экземпляра происходит в операции, которую подклассы могут легко переопределить, напримерв качестве операции инициализации .

  1. «Другие шаблоны проектирования» включают абстрактную фабрику, конструктор и прототип.Разве для прототипа не нужны новые классы, как и для фабричного метода?Или я неправильно понимаю, что означает «требовать новых классов»?

  2. Что означает «когда экземпляр создается в операции, которую подклассы могут легко переопределить, например в операции инициализации»?Почему фабричный метод в этом случае не нужен?

1 Ответ

2 голосов
/ 11 июня 2019

Позвольте мне начать с реализации java шаблона фабричного метода:

interface Product {
}

class ConcreteProduct implements Product {
}

abstract class Creator {

    abstract Product createProduct();

    final void usage() {
        final Product product = createProduct();
        System.out.println(product);
    }
}

final class ConcreteCreator extends Creator {

    @Override
    Product createProduct() {
        return new ConcreteProduct();
    }
}

1) Для первого вопроса давайте рассмотрим предложение

Другие шаблоны проектирования требуютновые классы, тогда как Factory Method требует только новой операции.

Учитывая новую реализацию Product, шаблон фабричного метода требует нового подкласса, так что это не может быть тем случаем, о котором идет речь в предложении.Вместо этого, контекст здесь, вероятно, заключается в том, что в методе Creator.usage требуется новая зависимость, например, от interface Item.В этом случае новые классы не требуются, мы просто добавляем метод abstract Item createItem() к существующему Создателю и его подклассам.

Сравните это с шаблоном прототипа.Во-первых, давайте изменим пример кода, чтобы можно было применить шаблон прототипа:

interface ProductPrototype extends Product {

    ProductPrototype prototypeCopy();
}

class ConcreteProductPrototype implements ProductPrototype, Product {

    @Override
    public ProductPrototype prototypeCopy() {
        return new ConcreteProductPrototype();
    }
}

abstract class Creator {

    final static boolean usePrototype = false;

    abstract Product createProduct();

    final void usage(final ProductPrototype prototype) {
        final Product product;

        if (usePrototype) {
            product = prototype.prototypeCopy();
        } else {
            product = createProduct();
        }

        System.out.println(product);
    }
}

Теперь, если добавлен новый Item, который мы хотим использовать в нашем создателе, нам также нужно добавить новые классыItemPrototype и подкласс для каждой конкретной реализации Item.

2) Для второго вопроса

Люди часто используют фабричный метод в качестве стандартного способа создания объектов, но этоне требуется, когда [...] создание экземпляра происходит в операции, которую подклассы могут легко переопределить, например в операции инициализации.

давайте рассмотрим пример кода:

interface Product {
}

class ConcreteProduct implements Product {
}

class DefaultProduct implements Product {
}

abstract class Creator {

    Product product;

    void initialize() {
        product = new DefaultProduct();
    }
}

final class ConcreteCreator extends Creator {

    @Override
    void initialize() {
        product = new ConcreteProduct();
    }
}

Заводской метод не требуется, поскольку метод (легко) переопределяется в подклассе.Обратите внимание, что в первоначальном примере фабричный метод необходим, потому что мы не хотим переопределять метод usage в каждом подклассе (то есть он может не быть легко переопределенным).

...