这是工厂模式的有效用法吗?多重依赖
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);
实际上看起来更直接。
我想创建一组依赖项而不是到处注入它们。工厂模式会支持这个想法吗?还是有另一种模式来处理它?
例如:
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);
实际上看起来更直接。