使用服務工廠在服務配置是在一些特殊情況下,更好的決策:
1)創建服務定義爲老年PHP類,因爲在過去,創建邏輯往往隱藏靜態工廠類 例如內,Doctrine_Core :: getTable()
public static function getTable($componentName)
{
return Doctrine_Manager::getInstance()->getConnectionForComponent($componentName)->getTable($componentName);
}
https://github.com/doctrine/doctrine1/blob/master/lib/Doctrine/Core.php
2)一個使用工廠服務和方法用於檢索服務的特別好的例子是Doctrine存儲庫的 案例。當你需要一個,你通常會注入實體管理器作爲 構造函數的參數,並在以後檢索特定的資源庫:
use Doctrine\ORM\EntityManager;
class SomeClass
{
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function doSomething()
{
$repository = $this->entityManager->getRepository('User');
}
}
但是使用工廠服務和方法,你可以直接注入正確的庫本身:
class SomeClass
{
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
}
...
<service id="some_service" class="SomeClass">
<argument type="user_repository" />
</service>
...
<service id="user_repository" class="UserRepository"
factory-service="entity_manager" factory-method="getRepository">
<argument>User</argument>
</service>
通過查看SomeClass的構造函數參數,立即清楚它需要一個 用戶存儲庫,它比SomeClass需要EntityManager的早期示例更具體和更具通信性。除了使類本身更清潔,也會使 它更容易創建一個獨立的對象存儲庫,當你正在編寫單元測試這個 類。而不是創建兩個實體管理器和庫一個模擬的,你只需要 創建一個存儲庫本身。
缺點是(按Matthias ):
我反對靜態工廠方法的工廠類是 靜態代碼是全局代碼,並且該執行該代碼可能有側面 無法隔離的影響(例如在測試場景中)。 此外,這種靜態工廠方法的任何依賴性必須由定義爲靜態的本身,這對隔離也是非常不利的,並且 可以防止您用自己的 代碼替換(部分)創建邏輯。工廠對象(或工廠服務)略好。 然而,需要對他們非常有可能指向某種設計 問題。服務不應該需要工廠,因爲它只會以預定的(確定的)方式創建 一次,並且從此 可以被任何其他對象完全重用。這是 動態有關服務的唯一的東西,應該是那個 是
其他幾個人要求其公共接口的一部分的方法的參數,發佈您的特定使用案例的詳細信息。尤其要區分「編譯時」配置和基於請求的「運行時」配置。 – Cerad