在 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