У меня есть приложение MVC с четко определенной моделью предметной области, с сущностями, репозиториями и уровнем обслуживания.
Чтобы не создавать экземпляры классов обслуживания внутри контроллеров и, следовательно, не связывать контроллеры с логикойчто не устраивает их, я создал помощник, который действует как своего рода Service Locator , но, прочитав немного, я понял, что много разработчиков:
Скажите, что сервисный локатор на самом деле является антишаблоном.Но я думаю, что моя реализация не является анти-шаблоном.
Причина, по которой они считают Service Locator анти-шаблоном, заключается в том, что он скрывает зависимости, однако я внедряю единственную зависимость (Entity Manager, и этозависимость, вероятно, не изменится, поскольку она находится в сигнатуре интерфейса службы), требуемой классом службы, в момент создания экземпляра локатора службы.
Вот мой код:
<?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' ) );
И как я использую этот помощник в моих контроллерах:
//Some Controller
$myService = $this->_helper->service( 'MyService' ); //returns an instance of the class App\Domain\Service\MyService
$result = $myService->doSomethingWithSomeData( $this->getRequest()->getPost() );
//etc...
- Моя реализация верна?
- Это действительно анти-паттерн?
- С какими возможными проблемами я могу столкнуться?
- Как я могу реорганизовать свой код для устранения этого анти-паттерна, но продолжить сфункциональность?