2011-03-25 157 views
7

我目前使用IoC來提供項目中存儲庫的具體實現。我讀過的所有示例都使用接口作爲服務的定義。但是,閱讀微軟建議,建議使用prefer abstract classes over interfacesIoC服務的抽象類或接口?

我發現這與模板模式相結合可以減少重複。例如給一個Product類屬性IsActive我可以用一個接口庫,如:

interface IProductRepository 
{ 
    IEnumerable<Product> Load(); 
} 

如果一個共同的任務就是裝載活躍產品,那麼我需要做的:

IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive); 

其中repository是一個具體的實現。如果我用一個抽象類,如:

abstract class ProductRepository 
{ 
    protected abstract IEnumerable<Product> LoadCore(); 

    public IEnumerable<Product> Load() 
    { 
     return LoadCore().Where(x => x.IsActive); 
    } 
} 

然後,我可以使用

IEnumerable<Product> activeProducts = repository.Load(); 

所有執行加載有源產品裝載產品信息是派生ProductRepository所以沒有在contrete類中耦合到持久層。如果發現有另一個通常執行的活動,則可以將其作爲無法使用接口完成的非重大更改添加到基類中。

使用接口而不是抽象類有什麼好處嗎?使用抽象類可能會遇到什麼潛在的缺點?

我正在使用Castle Windsor作爲IoC控制器和.Net框架3.5。

回答

7

我不認爲這個問題取決於IoC;大多數這些框架不關心你使用的是什麼。

使用接口到抽象基類之間的大問題是interfaces cannot be versioned well

因爲這個原因,抽象基類通常是更好的選擇。我認爲使用抽象基類沒有任何缺點,除了獲得諸如「爲什麼我不能創建這種類型的實例?」之類的支持問題之外。

+1

+1我完全同意,是否使用接口或抽象類與DI中抽象的使用是完全正交的......我不同意抽象基類的定性評估。 ..有很多缺點,但這是另一個討論:) – 2011-03-25 20:17:39

+0

@mark有什麼缺點?老實說,我想不出任何我的頭頂... – Will 2011-03-27 03:06:01

+4

那麼,一般來說,我們知道,我們應該'贊成組合繼承',所以使用基類違背這一建議。在更具體的層面上,角色接口傾向於比標題接口提供更好的抽象。然而,角色接口的真正好處是一個類可以實現多個接口。這對於繼承來說是不可能的,所以使用基類將我們引向標題接口的方向,從而導致糟糕的抽象。 – 2011-03-27 06:29:38

2

推薦來自Framework Design Guidelines。 Microsoft的這一建議專門用於可重用的類庫。換句話說:像.NET框架本身這樣的框架。如果您正在創建業務線應用程序,則此準則不適用。它不適用,因爲您不太可能在一行業務應用程序中出現版本問題,因爲您可以控制與您的類/接口進行通信的所有客戶端代碼。這當然不適用於可重用的庫。

即使the article of Phil Haack,其中威爾引用描述此:

同樣,這些準則是特定 到Framework開發(用於 靜態類型語言),而不是 其他類型的軟件 發展。

因此,刪除版本問題可能不是使用基類的好參數。保持代碼乾燥,但可能是。但是,使用基類和接口不是相互排斥的;你可以讓你的abstract class ProductRepository實現IProductRepository。但是,如果你這樣做,揭露除IProductRepository之外的東西將是一個壞主意。