refactoring.guru дает определение паттернам "Простая фабрика" и "Фабричный метод".
Паттерн Простая фабрика — это класс, в котором есть один метод с большим условным оператором (switch — прим. автора), выбирающим создаваемый продукт. Этот метод вызывают с неким параметром, по которому определяется какой из продуктов нужно создать. У простой фабрики, обычно, нет подклассов.
class UserFactory {
public static function create($type) {
switch ($type) {
case 'user': return new User();
default:
throw new Exception('Wrong user type passed.');
}
}
}
Паттерн Фабричный метод — это устройство классов, при котором подклассы могут переопределять тип создаваемого в суперклассе продукта.
Источник: https://refactoring.guru/ru/design-patterns/factor...
Далее приводится пример "Фабричного метода" без switch.
Таким образом, "Простая фабрика" — это класс, а "Фабричный метод" — устройство классов. Но! Куда пропал switch в фабричном методе? Каким образом клиентский код будет определять какая именно фабрика и какой именно продукт ему нужен, если отсутствует условный оператор?
Допускается ли использовать условный оператор (switch) как в классе "абстрактной" фабрики, чтобы выбрать нужную фабрику, так и в классе конкретной фабрики, чтобы выбрать нужный продукт? Привожу пример моей реализации "Фабричного метода".
interface ProductFactoryInterface
{
public static function create(string $product): ProductInterface;
}
class ProductFactory
{
public static function create(string $factory, string $product): ProductInterface
{
switch ($factory) {
case 'acme':
return AcmeFactory::create($product);
default:
throw new InvalidArgumentException();
}
}
}
class AcmeFactory implements ProductFactoryInterface
{
public static function create(string $product): ProductInterface
{
switch ($product) {
case 'foo':
return new FooProduct();
case 'bar':
return new BarProduct();
default:
throw new InvalidArgumentException();
}
}
}
interface ProductInterface
{
public function getName(): string;
}
class FooProduct implements ProductInterface
{
public function getName(): string
{
return 'foo';
}
}
class BarProduct implements ProductInterface
{
public function getName(): string
{
return 'bar';
}
}
// клиентский код
$product = ProductFactory::create('acme', 'foo');
$product->getName();