2013-04-10 63 views
3

我有一個自定義框架,我有一個類/方法使用我自己的Cache類。使用自定義提供者類去除緊密耦合

目前它緊密耦合。因此,一個方法實例化Cache類是這樣的:

public function someMethod () 
{ 
    $cache = new Cache\HHCache(); 
} 

我想RO刪除緊耦合,但是這其實這裏我有點卡住了。

我認爲這是一個好主意,創建某種ServiceProvider類。但我不確定這是否是正確的方法。

要開始我有HHConfig文件,其中有一個static屬性,其中定義了緩存類。總之:

class HHConfig 
{ 
    static $_cacheClass = '\Core\Cache\HHCache'; 
} 

所以基本上我有這樣一類,這是我的框架核心部分功能:

interface IHHServiceProvider 
{ 
    public function getService (); 
} 

然後,我有另一個類,將實現該interface

class HHCacheProvider implements IHHServiceProvider 
{ 
    public static function getService () 
    { 
     $class = HHConfig::$_cacheClass; 
     return new $class(); 
    } 
} 

所以現在someMethod可以使用HHCacheProvider類來獲得一個Cache類的一個實例。

public function someMethod () 
{ 
    $cache = HHCacheProvider::getService (); 
} 

IHHServiceProvider是不是真的像典型Provider類,因爲你不能真正註冊任何Services它。它只是在HHConfig類看起來什麼「類」加載和返回的例子。

所以不知何故,這種方法並不適合我,但我確實認爲它顯示了我想達到的目標。我可以通過哪些方式改善這一點?


請注意,我不是在尋找這個簡單的依賴注入模式。因爲我不想將我的Cache類注入到每個構造函數類中。我需要一個非緊密耦合的以某種方式從方法中獲取HHCache類的實例的方法。

某些可以成爲我框架一部分的提供者類似乎是正確的方向。

+0

爲什麼*不*只是注入了'CacheFactory'?無論你做什麼,都不涉及注射,你不會減少耦合,你只是將耦合轉移到其他關係。 – DaveRandom 2013-04-10 13:15:55

+0

@DaveRandom是的,我意識到這一點,但只要它可以是一個泛型類,它是我的框架的「核心」的一部分,那麼它並沒有那麼糟糕。我希望開發人員能夠用自己的實現「覆蓋」默認的'HHCache'類。使用DI當然是減少耦合的最佳方式。但我真的更像一個'提供者'模式。 - 這樣一個「開發人員」可以簡單地改變'HHConfig'中的'HHCache'類,並指定要使用什麼'Cache'類。作爲回報的Cache類必須實現一個保證它具有所需要的方法的接口。 – w00 2013-04-10 13:22:54

+0

ServiceProvider實際上是某種單身人士和單身人士是邪惡的:http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/所以我強烈推薦DI或至少一個工廠方法,也許在一個普通的基類或其他東西。 – 2013-04-10 14:15:52

回答

2

注: 「提供者」 意味着什麼。這個名字沒有模式。

而不是做一些神奇的「privider」,你應該看看工廠模式。基本上,這個想法是如下:

  1. 您在將使用一些服務(假設Cache是不是你的目標服務的唯一形式)班注入的工廠。

  2. 從工廠它所需要的服務類的要求:

    • if服務已被初始化一次,它會返回一個實例,你
    • else它創建新實例,它和商店退貨你到「消費者」

最簡單的代碼例子是這樣的:

class ServiceFactory 
{ 
    private $storage = []; 

    public function create($name) 
    { 
     if (false === array_key_exists($name, $this->storage)) 
     { 
      $instance = new $name; 
      $this->storage[$name] = $instance; 
     } 

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

} 

這是一個非常簡單的例子,但即使在這種情況下,如果在任意數量的對象注入這個工廠的實例,他們都將有機會獲得實例的同一個池。

如果你決定尋找到DI容器的概念,那麼工廠也是地方,它是適當的使用他們,沒有他們降低爲服務定位反模式。

..而且你可能會發現一些有價值的講座:

+0

將實例存入存儲的目的是什麼?這僅僅是爲了表現嗎?否則,它看起來像單身模式或換句話說 - 看起來像全局狀態。 – Andrew 2014-10-21 08:38:57

+0

@Andrew,請觀看關聯的第二個視頻。 – 2014-10-21 10:49:34

+0

我做到了。我的問題沒有改變。如果我將對象實例保存在存儲器中,並在一個類中使用此工廠(可能會更改對象屬性數據),然後在另一個類中使用同一工廠(和對象) - 我具有全局狀態,則該對象將提示它來自一個類到另一個。沒有分離。不好。 ? – Andrew 2014-10-21 11:08:32

1

根據OP請求

特別是因爲它將是框架的一部分,所以應該注入緩存。 DI Container是最好的解決方案,您可以將實際的Cache實現配置爲單例。您提出的解決方案與某些服務緊密耦合,難以單獨測試。實際上它看起來更像是一個服務定位模式而不是提供者。

如果您使用的工廠不會替換DI容器。 DI的一點是,代碼不應該耦合到外部靜態服務。除非你有很好的理由,否則任何對象都應該只使用注入的(通過構造函數或方法參數)依賴項。