使用继承模板化服务依赖注入
service dependency injection templated using inheritance
使用模板模式(继承)为 class 注入依赖项的优缺点是什么。
假设我正在创建一堆业务服务 classes,例如,作为 SecurityService 实现的 ISecurityService。
而且,如果我知道所有业务服务(包括 ISecurityService)will/should 都依赖于 IBusinessContext 来获取服务上下文信息,我可以使用模板模式(使用继承)来 achieve/enforce 吗?
方法 #1:
public interface IBusinessContext
{
public int Property { get; }
}
public interface IService
{
public IBusinessContext Context { get; }
}
public abstract class ServiceBase : IService
{
public IBusinessContext Context { get; }
public ServiceBase(IBusinessContext context) { _context = context; }
}
public interface IBusinessServiceN : IService
{
public void DoSomething();
}
public class BusinessServiceN : ServiceBase, IBusinessServiceN
{
public SecurityService(IBusinessCnotext context)
: base(context) { }
public void DoSomething() { }
}
方法 #2:
public interface IBusinessContext
{
public int Property { get; }
}
public interface IBusinessServiceN
{
public void DoSomething();
}
public class BusinessServiceN : IBusinessServiceN
{
private IBusinessContext _context;
public SecurityService(IBusinessCnotext context) { _context = context; }
public void DoSomething() { }
}
首选哪种方法,为什么?
第 2 个,因为为什么服务将 IBusinessContext
公开为 public 属性 是有意义的?它没有。这是它的依赖项之一,不需要通过接口公开,甚至不需要在具体 class.
上公开
消费 IService
的合同不/不应包括创建具体 class 以实现 IService
的合同。如果我可以在没有 IBusinessContext
实例的情况下实现 IService
,那是一件好事,尤其是在编写单元测试和模拟 IService
时。或者,如果我的 IService
实现需要一个 ICompleteContext
而不是包含一个 IBusinessContext
,又不应该像在 #1.
中那样用某些接口人为地限制它怎么办?
这完全取决于您的要求。除非您的摘要中有可重用代码 class,否则方法 #1 不会增加任何好处。
当您有一个通用的工作流并且您确定该工作流不会改变时,模板方法模式真正发挥作用;虽然子实现可能会改变某些步骤,但它们可能不会改变工作流结构。
所以假设在您的 DoSomething 方法中您有一个 "strict" 工作流程,其中一些步骤与继承 classes:
相同
public virtual void DoSomething() {
DoSomethingFirst(); // -> common to all classes
DoSomethingAfter(); //-> each class has unique implementation
}
你的基础 class 可以采用以下形式:
public abstract class ServiceBase : IService
{
public IBusinessContext Context { get; }
public ServiceBase(IBusinessContext context) { Context = context; }
public void DoSomethingFirst() {
// common implementation here
}
public abstract void DoSomethingAfter();
public virtual void DoSomething() {
DoSomethingFirst();
DoSomethingAfter();
}
}
还有你的具体 class:
public class BusinessServiceN : ServiceBase, IBusinessServiceN
{
public BusinessServiceN(IBusinessContext context)
: base(context) { }
public override void DoSomethingAfter()
{
//Your custom implementation here
}
}
如您所见,您的 DoSomething()
方法和 shared/reusable DoSomethingFirst()
方法中有一个强制结构。
使用模板模式(继承)为 class 注入依赖项的优缺点是什么。
假设我正在创建一堆业务服务 classes,例如,作为 SecurityService 实现的 ISecurityService。
而且,如果我知道所有业务服务(包括 ISecurityService)will/should 都依赖于 IBusinessContext 来获取服务上下文信息,我可以使用模板模式(使用继承)来 achieve/enforce 吗?
方法 #1:
public interface IBusinessContext
{
public int Property { get; }
}
public interface IService
{
public IBusinessContext Context { get; }
}
public abstract class ServiceBase : IService
{
public IBusinessContext Context { get; }
public ServiceBase(IBusinessContext context) { _context = context; }
}
public interface IBusinessServiceN : IService
{
public void DoSomething();
}
public class BusinessServiceN : ServiceBase, IBusinessServiceN
{
public SecurityService(IBusinessCnotext context)
: base(context) { }
public void DoSomething() { }
}
方法 #2:
public interface IBusinessContext
{
public int Property { get; }
}
public interface IBusinessServiceN
{
public void DoSomething();
}
public class BusinessServiceN : IBusinessServiceN
{
private IBusinessContext _context;
public SecurityService(IBusinessCnotext context) { _context = context; }
public void DoSomething() { }
}
首选哪种方法,为什么?
第 2 个,因为为什么服务将 IBusinessContext
公开为 public 属性 是有意义的?它没有。这是它的依赖项之一,不需要通过接口公开,甚至不需要在具体 class.
消费 IService
的合同不/不应包括创建具体 class 以实现 IService
的合同。如果我可以在没有 IBusinessContext
实例的情况下实现 IService
,那是一件好事,尤其是在编写单元测试和模拟 IService
时。或者,如果我的 IService
实现需要一个 ICompleteContext
而不是包含一个 IBusinessContext
,又不应该像在 #1.
这完全取决于您的要求。除非您的摘要中有可重用代码 class,否则方法 #1 不会增加任何好处。
当您有一个通用的工作流并且您确定该工作流不会改变时,模板方法模式真正发挥作用;虽然子实现可能会改变某些步骤,但它们可能不会改变工作流结构。
所以假设在您的 DoSomething 方法中您有一个 "strict" 工作流程,其中一些步骤与继承 classes:
相同public virtual void DoSomething() {
DoSomethingFirst(); // -> common to all classes
DoSomethingAfter(); //-> each class has unique implementation
}
你的基础 class 可以采用以下形式:
public abstract class ServiceBase : IService
{
public IBusinessContext Context { get; }
public ServiceBase(IBusinessContext context) { Context = context; }
public void DoSomethingFirst() {
// common implementation here
}
public abstract void DoSomethingAfter();
public virtual void DoSomething() {
DoSomethingFirst();
DoSomethingAfter();
}
}
还有你的具体 class:
public class BusinessServiceN : ServiceBase, IBusinessServiceN
{
public BusinessServiceN(IBusinessContext context)
: base(context) { }
public override void DoSomethingAfter()
{
//Your custom implementation here
}
}
如您所见,您的 DoSomething()
方法和 shared/reusable DoSomethingFirst()
方法中有一个强制结构。