在 PHP 中从工厂类实例化对象

在 PHP 中使用工厂从大量依赖项构建对象时,我们可能想知道如何最好地从组合根(通常是 index.php 文件)实例化对象。

从构造函数类创建对象不起作用,因此我们需要以不同的方式处理问题。

我提出以下语法:

$http_client = (new my_project\lib\factories\http_client_factory())->build();

问题

在使用 new 关键字实例化工厂类时,我们发现无法直接从构造函数类返回最终对象,这迫使我们首先从组合根调用 create() 或者 build() 方法。

我们可以将对象加载到工厂的公共属性中,但这会很脏,因为无论何时使用它,我们都需要通过此属性访问对象。
你也可以为你的工厂使用单例模式,但人们往往不喜欢单例。

必须将对象重新分配给组合根中的外部变量也不是很可取,那么我们该怎么办?
以下显然不起作用:

$http_client = new myProject\lib\factories\http_client_factory()->build();

我们可能还想避免这种情况:

$factory_product = new myProject\lib\factories\http_client_factory();
$http_client = $factory_product->build();

然而,这个问题可以通过将新语句括在一些括号中来解决,将我们的工作减少到这个漂亮的单行代码:

$http_client = (new myProject\lib\factories\http_client_factory())->build();

我们需要在工厂类中做的所有事情就是在公共 build() 方法中包含依赖项。
当然,我们应该在工厂内部使用依赖注入。

一个简单的工厂类

当我们获得一个由多个其他对象(依赖项)组成的对象,并且我们希望简化该对象的实例化时,工厂非常有用。
它还避免了为了实例化而必须记住对象所需的所有依赖项。

使用 new 关键字(紧耦合)在其他对象内部实例化对象通常被认为是一种不好的做法,但对此有一个例外,那就是在工厂类中(松散耦合)。

工厂类的基本示例如下所示:

class file_handler_factory
{
    public static function build()
    {
        $superglobals = new \doorkeeper\lib\superglobals\superglobals();
        $helpers = new \doorkeeper\lib\php_helpers\php_helpers();
        $file_types = new \doorkeeper\lib\file_handler\file_types();
        return new \doorkeeper\lib\file_handler\file_handler($helpers, $superglobals, $file_types);
    }
}

以上实际上取自我正在从事的一个真实项目,虽然仍在进行更改,但它是如何编写工厂的有用示例。

我们也可以将每个依赖项分离到它自己的方法中,但我个人发现这只会导致意大利面条式代码。
例如:

class file_handler_factory
{
    public function build() {
      $this->create_superglobals();
      $this->create_helpers();
      return $this->create_file_handler();
    }
    private function create_superglobals()
    {
        $this->superglobals = new \doorkeeper\lib\superglobals\superglobals();
    }
    private function create_helpers()
    {
        $this->helpers = new \doorkeeper\lib\php_helpers\php_helpers();
    }
    private function create_file_handler()
    {
        $file_types = new \doorkeeper\lib\file_handler\file_types();
        return new \doorkeeper\lib\file_handler\file_handler($this->helpers, $this->superglobals, $file_types);
    }
}
日期:2020-06-02 22:15:40 来源:oir作者:oir