这是Factory模式的有效用法吗?多个依赖项

时间:2018-02-21 22:54:13

标签: php unit-testing design-patterns phpunit tdd

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

例如:

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();   

1 个答案:

答案 0 :(得分:0)

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

$request = new WhateverRequestClass;
$service = new PassportCheckService($request, new PassportCheckSoapClient, new PassportCheckResponse);
$response = $service->execute();   
在可读性,可维护性和可测试性方面,

实际上是独立服务的最佳解决方案。

多个CheckServices

但是,如果您想支持多种服务,将服务的组合提取到自己的类中会带来好处。

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);
    }
}

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

调用特定服务将如下所示:

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

建议的重构

除了上述内容之外,我还建议重构服务类本身,因此请求会从构造函数中删除。这改变了用法 到:

$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);

实际上看起来更直接。