1. case сам по себе не есть плохо, и это не считается дурным тоном. т.е. использовать конструкцию case можно и нужно.
2. Давайте подумает чем характеризуется объект экземпляра класса, а потом перейдем к фабрике.
Объект прежде всего характеризуется данными хранящимися внутри него. Т.е. Фабрика должна внутри себя хранить то что она выпускает (строит) и всю информацию о нем.
3. не используйте рефлекшен. это плохо это дурной код, без крайней необходимости не нужно. Обычно рефлекшены не используются в клиентском коде, только непосредственно в самих фреймворках. но раз вы задаете вопросы про фабрики, вы фреймворк не пишите, а значит и использование рефлекшенов вам не нужно.
4. Взгляните на оператор new (например, new Factory()) по сути оператор new и есть фабрика, которая из класса создает объект с уникальными (а может и не всегда) наборами данных.
5. в ссылке выше, вам дали информацию по рефакторингу switch но если прочитать там, написано,
не стоит трогать если
Зачастую оператор switch используется в фабричных паттернах проектирования (Фабричный метод, Абстрактная фабрика) для выбора создаваемого класса
вот в данном случае не нужно трогать.
Почему лучше использовать switch?
- потому что когда через год, или два зайдете в эту фабрику, навряд ли вы захотите разбираться в рефлекшенах, и не интуитивных выражениях. А когда все есть в switch вы сразу увидите перед глазами какие объекты может выпускать фабрика + по аналогии создать подобный объект используя менее трудозатрат (почти копипаст).
Вот тут хороший пример фабрики:
https://refactoring.guru/ru/design-patterns/factor...
или можно так:
/**
* Интерфейс Продукта объявляет операции, которые должны выполнять все
* конкретные продукты.
*/
interface Product
{
public function operation(): string;
}
/**
* Конкретные Продукты предоставляют различные реализации интерфейса Продукта.
*/
class ConcreteProduct1 implements Product
{
public function operation(): string
{
return "{Result of the ConcreteProduct1}";
}
}
class ConcreteProduct2 implements Product
{
public function operation(): string
{
return "{Result of the ConcreteProduct2}";
}
}
class Factory implements Product{
private $product;
function __construct(string $productClass){
switch($productClass){
case default:
case ConcreteProduct1::class:
$product = new ConcreteProduct1();
break;
case ConcreateProduct2::class:
$product = new ConcreateProduct2();
break;
}
$this->product = $product;
}
public function operation(): string
{
return $this->product->operation();
}
}
$product = new Factory(ConcreateProduct1::class);
echo $product->operation();
В данном случае Разрешено менять старый код, но только в пределах switch.