2016-04-21 63 views
-1

我的問題更多的是懷疑什麼是最佳解決方案。注入提供者服務或容器。良好的做法

想象一下,我們需要實現一個處理程序,這取決於來自實體的一個參數。 讓我解釋一下

OPTION1

  • 服務/供應商/ HSBCProvider
  • 服務/供應商/ BarclaysProvider
  • 服務/ BankHandler
  • 控制器/ BankController

BankHandler

class BankHandler { 
    private $container; 
    function __contructor($container) { 
    $this->container = $container; 
    } 
    function create($account) { 
    $provider = $this->container->get('service.provider.'.$account->getName()); 
    $provider->do(); 
    } 
} 

BankController行動

public function createAction($id) { 
    $account = $repository->getAccount($id); 
    $bankHandler = $this->get('service.bank_handler'); 
    $bankHandler->create($account); 
} 

OPTION 2

  • 服務/提供者/ HSBCProvider
  • 服務/提供者/ BarclaysProvider
  • 控制器/ BankController

BankController行動

public function createAction($id) { 
    $account = $repository->getAccount($id); 
    $bankProvider = $this->get('service.provider.'.account->getName()); 
    $bankProvider->do(); 
} 

使用此選項的BankHandler類不是不再需要

我簡化所有的邏輯裏面的創建和行動。

我不喜歡選項1因爲我正在注射容器。 我不喜歡選項2 cos動作控制器有太多的邏輯(胖控制器?)。

還有其他更好的解決方案嗎?

+0

在你的第一個選擇,你的'BankHandler'類並不一定要依賴於容器。只需添加一個方法來向一個名稱註冊一個提供者,並在'create()'方法中返回這個提供者(或者也可以在那裏應用您需要的任何邏輯)。 – xabbuh

+0

@xabbuh我不想在create方法中實例化提供程序類,因此我必須將其注入基於帳戶名稱的構造函數中。提供者服務已經正確註冊 – Mauro

+1

這個問題-2有多糟? – Mauro

回答

0

與所有提供者創建註冊表服務,將其注入處理程序並從中獲取提供程序。沿着線的東西...

class BankProviderRegistry 
{ 
    /** 
    * @var array|BankProviderInterface[] 
    */ 
    private $providers = array(); 

    public function __construct(array $providers = array()) 
    { 
     foreach($providers as $name => $provider) { 
      $this->addProvider($name, $provider); 
     } 
    } 

    /** 
    * Add provider to registry 
    * 
    * @param string $name 
    * @param BankproviderInterface $provider 
    */ 
    public function addProvider($name, BankProviderInterface $provider) 
    { 
     $this->provider[$name] = $provider; 
    } 

    /** 
    * Get provider by name 
    * 
    * @param string $name 
    * @return BankproviderInterface 
    */ 
    public function getProvider($name) 
    { 
     if (!isset($this->providers[$name])) { 
      throw new \Exception(sprintf('Provider "%s" is not registered', $name)); 
     } 

     return $this->providers[$name]; 
    } 
} 

您既可以在你的服務,如添加這些..

app.registry.bank_provider: 
    class: AppBundle\Registry\BankProviderRegistry 
    arguments: 
     - 
      'a name': '@app.provider.a_name' 
      'another name': '@app.provider.another_name' 

..,在你的DI擴展,在編譯過程,也許別的地方我沒有想到。

然後你通過這個到您的處理程序,並獲得供應商如..

class BankHandler 
{ 
    private $registry; 

    public function __contruct(BankProviderRegistry $registry) { 
     $this->registry = $registry; 
    } 

    public function create($account) { 
     $provider = $this->registry->getProvider($account->getName()); 
     $provider->do(); 
    } 
} 
+0

我喜歡你的想法。我唯一關心的是實例化大量注入註冊表的提供程序。 – Mauro

+0

我不喜歡這樣。無論用戶是否使用,您都將實例化服務。注入容器並在需要時調用服務比這更好。 – LMS94

+0

@ LM94。那麼你最喜歡的選擇是1? – Mauro