什么时候使用 DI 而不是抽象继承?
When to use DI over abstract inheritance?
我正在设计一个 class,它使用抽象 属性 来提供对字段的访问点。这是我的代码片段:
public abstract class PageBroker : WebBroker
{
public abstract IPageProvider Provider { get; }
}
public class ArticleBroker : PageBroker
{
public override IPageProvider Provider { get; } = new ArticleProvider();
}
我意识到我可以将其重构为使用 DI,如下所示:
public class PageBroker : WebBroker
{
public PageBroker(IPageProvider provider)
{
this.Provider = provider;
}
public IPageProvider Provider { get; private set; }
// implementation...
}
// no derived class, just new PageBroker(new ArticleProvider())
在什么情况下一种技术比另一种更合适?
这是关于支持组合而不是继承,这是一个很好的指导方针。我建议,由于 PageBroker 有 IPageProvider,您应该使用 DI。 class 的用户可以提供没有继承的替代实现,比如注入一个测试 IPageProvider。仅出于这个原因,我会选择 DI。
如果存在基于 IPageProvider 的存在差异,以至于在语义上使用不同的提供者需要来反映是关系(a PageBroker 的子类型),那么我会使用抽象 class.
如前所述,我将使用 DI 填充您的 Provider。也就是说,您希望通过摘要 class 获得什么?如果只是简单的注入IPageProvider那就真的没什么好说的了。
但是,如果您有其他针对 WebBrokers 或 PageBrokers 的常用方法,那么为什么不同时使用这两种方法呢?
例如:
public abstract class WebBroker
{
private IPageProvider _pageProvider;
protected WebBroker(IPageProvider pageProvider)
{
_pageProvider = pageProvider;
}
public override void CommonThing(int someData)
{
var result = _pageProvider.CommonMethod(someData);
//do something with result
}
}
现在您所有的 WebBroker 都有使用 DI 传入的 _pageProvider 的 CommonThing 方法。
我同意 BJ Safdie 的回答。
也就是说,我认为主要区别在于,在第一个实现中,ArticleBroker 耦合到 IPageProvider(即 ArticleProvider)的特定实现。如果这是有意的,我认为没有问题。但是,如果您想在运行时提供 IPageProvider 的实现(在生产代码中或通过 mocks/fakes 在单元测试中),那么注入依赖项是更好的选择。
我正在设计一个 class,它使用抽象 属性 来提供对字段的访问点。这是我的代码片段:
public abstract class PageBroker : WebBroker
{
public abstract IPageProvider Provider { get; }
}
public class ArticleBroker : PageBroker
{
public override IPageProvider Provider { get; } = new ArticleProvider();
}
我意识到我可以将其重构为使用 DI,如下所示:
public class PageBroker : WebBroker
{
public PageBroker(IPageProvider provider)
{
this.Provider = provider;
}
public IPageProvider Provider { get; private set; }
// implementation...
}
// no derived class, just new PageBroker(new ArticleProvider())
在什么情况下一种技术比另一种更合适?
这是关于支持组合而不是继承,这是一个很好的指导方针。我建议,由于 PageBroker 有 IPageProvider,您应该使用 DI。 class 的用户可以提供没有继承的替代实现,比如注入一个测试 IPageProvider。仅出于这个原因,我会选择 DI。
如果存在基于 IPageProvider 的存在差异,以至于在语义上使用不同的提供者需要来反映是关系(a PageBroker 的子类型),那么我会使用抽象 class.
如前所述,我将使用 DI 填充您的 Provider。也就是说,您希望通过摘要 class 获得什么?如果只是简单的注入IPageProvider那就真的没什么好说的了。
但是,如果您有其他针对 WebBrokers 或 PageBrokers 的常用方法,那么为什么不同时使用这两种方法呢?
例如:
public abstract class WebBroker
{
private IPageProvider _pageProvider;
protected WebBroker(IPageProvider pageProvider)
{
_pageProvider = pageProvider;
}
public override void CommonThing(int someData)
{
var result = _pageProvider.CommonMethod(someData);
//do something with result
}
}
现在您所有的 WebBroker 都有使用 DI 传入的 _pageProvider 的 CommonThing 方法。
我同意 BJ Safdie 的回答。
也就是说,我认为主要区别在于,在第一个实现中,ArticleBroker 耦合到 IPageProvider(即 ArticleProvider)的特定实现。如果这是有意的,我认为没有问题。但是,如果您想在运行时提供 IPageProvider 的实现(在生产代码中或通过 mocks/fakes 在单元测试中),那么注入依赖项是更好的选择。