Почему абстрактный Factory имеет дело с семействами и Factory Метод с генерированием одного объекта?

Из того, что я прочитал, абстрактный шаблон factory обычно относится к созданию нескольких объектов, все из которых связаны с одним и тем же семейством, а шаблон метода factory относится к созданию одного объекта.

Рассмотрим следующий пример, который отражает эти проблемы:

// Factory Method (base class) allowing for creation of families of objects
public class BasePizzaCreator{
    abstract ISauce CreateSauce();
    abstract IToppings CreateToppings();
    abstract ICrust CreateCrust();
}

// Abstract Factory (interface) defining contract to create a single object
public interface IPizzaFactory{
    abstract IPizza CreatePizza();
}

Очевидно, что вы можете использовать их таким образом - но является ли это нарушением духа шаблонов? Если да, то почему?

Что я действительно хочу здесь понять: Почему Abstract factory лучший подход для создания семейств связанных объектов, а метод factory - лучший подход к созданию единого объекта?

Ответ 1

В приведенных примерах BasePizzaCreator является абстрактной фабрикой, но IPizzaFactory - это не какой-либо шаблон проектирования GoF (хотя его иногда называют простой фабрикой).

Что касается того, почему Абстрактная Фабрика имеет дело с семействами продуктов, тогда как Фабричный Метод имеет дело с одним продуктом: это просто, как их определил GoF. В книге GoF упоминается, что наиболее распространенным способом реализации абстрактной фабрики является использование нескольких фабричных методов; но я не видел этого на практике. С точки зрения клиента, абстрактная фабрика может быть предпочтительнее, потому что клиенты вызывают ее через составление/делегирование, в отличие от фабричного метода, который требует, чтобы клиенты наследовали этот метод.

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

Ответ 2

Это разница в намерении этих двух шаблонов.

FactoryMethod: Определите интерфейс для создания объекта, но пусть подклассы определяют, какой класс необходимо создать. FactoryMethod позволяет классу отложить экземпляр к подклассам.

AbstractFactory: предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.

AbstractFactory классы часто реализуются с помощью FactoryMethods, но они могут быть реализованы даже с помощью Prototypes

Обычно начинайте дизайн с FactoryMethod и может развиваться по отношению к другим шаблонам создания, таким как AbstractFactory, Prototype или Builder

Я тоже согласен с ответом @jaco0646 относительно преимущества использования AbstractFactory (использует делегирование/состав) от клиента вместо использования FactoryMethod (который основан на наследовании)

Относительно вашего последнего запроса:

Почему Abstract Factory лучший подход для создания семейств связанных объектов, а метод Factory - лучший подход к созданию единого объекта?

Да. Оба они предназначены для разных целей, как указано в намерении.

AbstractFactory имеет преимущество в возврате одного из продуктов из семейства.

Преимущество FactoryMethod: он может возвращать один и тот же экземпляр несколько раз или может возвращать подкласс, а не объект этого точного типа.

Обратитесь к этой sourcemaking для лучшего понимания этих шаблонов.