我有一个抽象服务类SAbstract
,由ConcreteServiceA
和ConcreteServiceB
继承。现在我在我的控制器的工厂类中实例化ConcreteServiceA
并在我的控制器中注入服务。
在我的控制器中的特定操作中,我想与ConcreteServiceA
交换ConcreteServiceB
以更改行为。因为它们具有相同的接口(抽象类SAbstract
),所以我也可以将它注入到我的控制器中(服务是策略模式)。
但我不想直接在我的控制器中实例化ConcreteServiceB
以保持我的代码清洁(以便轻松重构和交换行为)。
一个可能的解决方案是为我的控制器创建第二个工厂,它注入ConcreteServiceB
而不是ConcreteServiceA
,但后来我复制了许多不好的代码......
另一个解决方案是在我的控制器中注入两个服务(但是这"闻起来像#34;就像坏代码一样)。
这是a delegator factory正确的方法吗?然后我必须在我的控制器中实现setter ...
有更好的方法吗?
我试图用示意图来形象化我的阶级关系。
AbstractService <|--<inherit>- ConcreteServiceA
AbstractService <|--<inherit>- ConcreteServiceB
Controller -<use>--> AbstractService
Controller:ActionA -<use>--> ConcreteServiceA:exportAction()
Controller:ActionB -<use>--> ConcreteServiceB:exportAction()
答案 0 :(得分:3)
在我的控制器中的特定操作中,我想与ConcreteServiceB交换ConcreteServiceA以更改行为。因为它们具有相同的界面。
您可以为每个操作配置路由以使用不同的控制器服务名称;然后配置控制器工厂以使用配置注入所需的服务。
路线配置可能如下所示。
'router' => [
'routes' => [
'foo' => [
'type' => 'literal',
'options' => [
'route' => '/foo',
'defaults' => [
'controller' => 'MyControllerWithFooService',
'action' => 'actionThatNeedsFooService',
],
],
],
'bar' => [
'type' => 'literal',
'options' => [
'route' => '/bar',
'defaults' => [
'controller' => 'MyControllerWithBarService',
'action' => 'actionThatNeedsBarService',
],
],
],
],
]
然后添加服务和控制器的配置。
'app_config' => [
'MyControllerWithFooService' => [
'service_name' => 'FooService',
],
'MyControllerWithFooService' => [
'service_name' => 'BarService',
],
],
'service_manager' => [
'factories' => [
'FooService' => 'FooServiceFactory'
'BarService' => 'BarServiceFactory'
],
],
'controllers' => [
'factories' => [
'MyControllerWithFooService' => 'MyControllerServiceFactory'
'MyControllerWithBarService' => 'MyControllerServiceFactory'
],
]
MyControllerServiceFactory
可能非常简单。
class MyControllerServiceFactory
{
public function __invoke($controllerManager, $name, $requestedName)
{
$sm = $controllerManager->getServiceLocator();
$config = $sm->get('config');
if (empty($config['app_config'][$requestedName])) {
throw new ServiceNotCreatedException('No config set!');
}
$serviceName = $config['app_config'][$requestedName]['service_name'];
$service = $sm->get($serviceName);
return new MyController($service);
}
}