我有一个 MVC 应用程序,其域模型定义良好,具有实体、存储库和服务层。
为了避免必须在我的控制器中实例化我的服务类,从而使我的控制器与不适合它们的逻辑混淆,我创建了一个充当某种Service Locator的助手,但在阅读了一些内容之后,我意识到许多开发人员:
- http://blog.tfnico.com/2011/04/dreaded-service-locator-pattern.html
- http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx
- http://underground.infovark.com/2010/06/18/the-service-locator-pattern-is-the-new-global-variable/
- http://www.andyfrench.info/2011/05/service-locator-anti-pattern_17.html
假设服务定位器实际上是一种反模式。但我认为我的实现不是反模式。
他们认为服务定位器是反模式的原因是因为它隐藏了依赖项,但是,我注入了唯一需要的依赖项(实体管理器,并且这个依赖项可能不会改变,因为它在服务接口的签名中)通过服务类,在我实例化服务定位器时。
这是我的代码:
<?php
namespace App\Controller\Action\Helper;
use Zend_Controller_Action_Helper_Abstract as Helper,
Doctrine\ORM\EntityManager;
/**
* Service Locator Helper
* @author JCM
*/
class Service extends Helper {
/**
* The actual EntityManager
* @var \Doctrine\ORM\EntityManager
*/
private $entityManager;
/**
* Services Namespace
* @var string
*/
private $ns;
/**
* @param EntityManager $entityManager
* @param string $ns The namespace where to find the services
*/
public function __construct( EntityManager $entityManager, $ns )
{
$this->entityManager = $entityManager;
$this->ns = $ns;
}
/**
* @param string $serviceName
* @param array $options
* @param string $ns
*/
public function direct( $serviceName, array $options = array(), $ns = null )
{
$ns = ( (!$ns) ? $this->ns : $ns ) . '\\';
$class = $ns . $serviceName;
return new $class( $this->entityManager, $options );
}
/**
* @param EntityManager $entityManager
*/
public function setEntityManager( EntityManager $entityManager )
{
$this->entityManager = $entityManager;
}
/**
* @return \Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* @param string $name
*/
public function __get( $name )
{
return $this->direct( $name );
}
}
向前端控制器注册动作助手:
//inside some method in the bootstrap
HelperBroker::addHelper( new App\Controller\Action\Helper\Service( $entityManager, '\App\Domain\Service' ) );
以及我如何在我的控制器中使用这个 Helper:
//Some Controller
$myService = $this->_helper->service( 'MyService' ); //returns an instance of the class App\Domain\Service\MyService
$result = $myService->doSomethingWithSomeData( $this->getRequest()->getPost() );
//etc...
- 我的实现是否正确?
- 真的是反模式吗?
- 我可能面临哪些可能的问题?
- 如何重构我的代码以消除这种反模式,但继续使用该功能?