如何使用遵循依赖倒置原则的工厂方法设计模式

问题描述 投票:0回答:1

我创建了一个这样的命令,但我想重构它以遵循 DI 原则:

    public function handle()
    {
        $productChoice = $this->argument('product');

        if ($productChoice == 1) {
            $product = new ProductA();
        } elseif ($productChoice == 2) {
            $product = new ProductB();
        } else {
            $this->error('Invalid product choice. Use 1 for ProductA or 2 for ProductB.');
            return;
        }

        if ($product instanceof ProductI) {
            $this->info($product->details());
        } else {
            $this->error('The selected product does not implement the ProductI interface.');
        }
    }

如您所见,该命令依赖于productA和productB。我的问题是如何重构它。

这里有一些想法,但我不确定哪个更好或者是否有更好的方法:

1- 创建如下所示的工厂类并将其注入到命令类中

class ProductFactory
{
    public function createProduct($productChoice)
    {
        switch ($productChoice) {
            case 1:
                return new ProductA();
            case 2:
                return new ProductB();
            default:
                return null;
        }
    }
}

2- 创建如下所示的服务提供者,并在类似

$product = $this->app->make("Product{$productChoice}")

的命令中使用它
public function register()
    {
        $this->app->bind('Product1', function () {
            return new ProductA();
        });

        $this->app->bind('Product2', function () {
            return new ProductB();
        });
    }
laravel design-patterns dependency-injection design-principles dependency-inversion
1个回答
0
投票

您需要的是从整数到类的映射。

在这种情况下,我更喜欢你建议的工厂保持干净和简单,但对创建方法进行一些小的修改:

public static function createFromId(int $productId): ProductI 
{
    return match ($productId) {
        1 => new ProductA(),
        2 => new ProductB(),
        default => throw new InvalidArgumentException('No product with this id'),
    };
}
  • 静态方法,所以你可以调用
    ProductFactory::createFromId($productChoice)
  • choice
    重命名为
    id
    (因为选择不是产品本身的属性)。
  • int
    输入提示。
  • 声明的返回类型
    ProductI
  • match
    声明而不是
    switch
  • 不允许
    null
    ,而是抛出异常。

您还可以决定在 id 无效时返回实现

EmptyProduct
DefaultProduct
ProductI

© www.soinside.com 2019 - 2024. All rights reserved.