【问题标题】:How to create an object using Factory method, instead of supplying alternative object constructor如何使用工厂方法创建对象,而不是提供替代对象构造函数
【发布时间】:2014-05-03 17:48:16
【问题描述】:

我在应用工厂模式时遇到了一些问题。

我有一个班级,我通常称之为Product($modelNumber, $wheelCount)。但是在我正在重构的遗留代码的一部分中,我没有 $modelNumber,只有 $productID,其中 {$modelNumber, $productID} 之间的链接在数据库中(或者在我的情况下,我可以对其进行硬编码,因为我目前只有少数产品)。

我需要能够使用$productId 创建我的课程,但是如何?

使用过程方法,我将拥有一个执行查找的函数,然后将该函数放在一个文件中,并将该文件包含在我需要进行查找的任何位置。因此这样做:

$modelNumber = modelLookup($productId)
Product($modelNumber, $wheelCount);

但是我该如何使用面向对象的方式呢?

注意:我在这里发布了更详细的情况:https://softwareengineering.stackexchange.com/q/233518/119333,这是概念上建议工厂模式(以及其他模式,如接口和函数指针传递)的地方,但我在尝试实现它们时碰壁了php。这似乎是一个简单的问题,但我认为有几种方法可以做到这一点,我对如何做有点迷茫。所以我需要一些帮助。

【问题讨论】:

    标签: php oop factory-pattern single-responsibility-principle


    【解决方案1】:

    我在 Programmers Exchange 上为您的 SRP 问题提供了概念性答案,但我想我可以在这里演示一下。

    您基本上想要的是一些其他对象,它们可以为您提供给定产品 ID 的型号。

    class ProductModelNumberProvider {
        public function findByProductId($productId) {
            // The lookup logic...
        }
    }
    

    您的工厂应该提供一个 setter 构造函数,以便它可以在内部使用此对象来在需要时查找型号。所以基本上你最终会得到一个与此类似的ProductFactory

    class ProductFactory {
        private $productModelNumberProvider;
        
        public function __construct(ProductModelNumberProvider $productModelNumberProvider) {
            $this->productModelNumberProvider = $productModelNumberProvider;
        }
    
        public function getProductByIdAndWheels($productId, $wheels) {
            $modelNumber = $this->productModelNumberProvider($productId);
            return $this->getProductByModelNumberAndWheels($modelNumber, $wheels);
        }
    
        public function getProductByModelNumberAndWheels($modelNumber, $wheels) {
            // Do your magic here...
            return $product;
        }
    }
    

    编辑

    再三考虑,setter 并不是最好的方法,因为必须有一个 ProductModelNumberProvider 实例。这就是为什么我将它移动到通过构造函数注入它。

    【讨论】:

    • 那么当你有$modelNumber时,你直接调用类,当你只有$prodiuctId时,你调用Factory,对吗?
    • 另外,当我有 $productID 时,我发现我需要先实例化 Provider 类,然后将其传递给工厂。像new ProductFactory(new ProductModelNumberProvider($productID)) 这样的东西。我知道是 DI,但看起来还是有点复杂
    • 您最好始终依靠工厂来创造产品。它为构建它们提供了清晰的界面和位置。所展示的方法一点也不复杂。您基本上在代码示例中发明了自己的界面,这与我的不同。
    • 也可以采用相同的方法来封装计算。理想情况下,工厂仅在您的应用程序启动时构建一次。不应为您要构建的每个产品都构建它。
    • 哎呀,错了。它应该是new ProductFactory(new ProductModelNumberProvider())->getProductByIdAndWheels(($productId, $wheels));。但是您将如何使用此 ProductFactory 按型号创建产品?
    【解决方案2】:

    我能想到这样的事情:

    $factory = new ProductBuilder();
    $factory->buildFromProductId($productId, $wheelCount); //uses modelLookup() internally
    $factory->buildFromModelNumber($modelNumber, $wheelCount); //just returns Product()
    

    它基本上是在过程函数之上创建一个类,但它确实将创建类的逻辑与查找映射分开。

    【讨论】:

      猜你喜欢
      • 2020-08-16
      • 2011-06-04
      • 1970-01-01
      • 2013-03-13
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 2013-09-24
      相关资源
      最近更新 更多