2011-03-25 110 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之外的东西将是一个坏主意。