这是工厂模式的有效用法吗?多重依赖

Is this a valid usage of the Factory pattern? multiple dependencies

我想创建一组依赖项而不是到处注入它们。工厂模式会支持这个想法吗?还是有另一种模式来处理它?

例如:

class PassportCheckFactory {
    protected $clientInstance;
    protected $responseInstance;

    public function buildDependancies() : bool
    {
        $this->clientInstance       = new PassportCheckSoapClient;
        $this->responseInstance    = new PassportCheckResponse;

        return true;
    }

    public function getResponseInstance()
    {
        return $this->responseInstance;
    }

    public function getClientInstance()
    {
        return $this->clientInstance;
    }
}

这会创建并保存我们将要使用的 类,因此我们不需要注入它们。

例如,我们可以这样做

$request = new WhateverRequestClass;
$factory = (new PassportCheckFactory)->buildDependancies();
$service = new PassportCheckService($request, $factory);
$response = $service->execute();

而不是:

$request = new WhateverRequestClass;
$service = new PassportCheckService($request, new PassportCheckSoapClient, new PassportCheckResponse);
$response = $service->execute();   

如果您想支持多个 CheckServices,您的方法很有意义。 如果 PassportCheckService 是唯一的,那么您示例中的工厂/服务定位器/专用容器只会增加开销。

$request = new WhateverRequestClass;
$service = new PassportCheckService($request, new PassportCheckSoapClient, new PassportCheckResponse);
$response = $service->execute();   

实际上是 stand-alone 服务在可读性、可维护性和可测试性方面的最佳解决方案。

多个检查服务

但是,如果要支持多个服务,将服务的组合提取到它自己的 class 中会带来好处。

class CheckServiceFactory
{
    public static function getService(Request $request, string $serviceType): CheckService
    {
        $type = ucfirst(strtolower($serviceType));

        $serviceClass  = $type . "CheckService";
        $clientClass   = $type . "CheckSoapClient";
        $responseClass = $type . "CheckResponse";

        return new $serviceClass($request, new $clientClass, new $responseClass);
    }
}

当然,class名称的生成取决于您的命名方案。

调用特定服务如下所示:

$request = new WhateverRequestClass;
$service = CheckServiceFactory::getService($request, 'Passport');
$response = $service->execute();   

提议的重构

除上述内容外,我建议重构服务 class 本身,以便请求脱离构造函数。这改变了用法 至:

$request = new WhateverRequestClass;
$service = CheckServiceFactory::getService('Passport');
$response = $service->handle($request);   

或者在单个服务的情况下:

$request = new WhateverRequestClass;
$service = new PassportCheckService(new PassportCheckSoapClient, new PassportCheckResponse);
$response = $service->handle($request);

实际上看起来更直接。