为什么不将所有服务类转换为Factory方法(而不是注入接口)?

时间:2010-03-25 07:21:35

标签: c# unit-testing dependency-injection structuremap

我们正在构建一个ASP.NET项目,并将所有业务逻辑封装在服务类中。有些是在域对象中,但通常那些是相当贫血的(由于我们正在使用的ORM,这不会改变)。为了更好地启用单元测试,我们为每个服务定义接口并使用D.I ..例如。这里有几个接口:

IEmployeeService
IDepartmentService
IOrderService
...

这些服务中的所有方法基本上都是任务组,并且这些类不包含私有成员变量(除了对依赖服务的引用)。在我们担心单元测试之前,我们只是将所有这些类声明为静态并让它们直接相互调用。现在,如果服务依赖于其他服务,我们将设置这样的类:

public EmployeeService : IEmployeeService
{
   private readonly IOrderService _orderSvc;
   private readonly IDepartmentService _deptSvc;
   private readonly IEmployeeRepository _empRep;

   public EmployeeService(IOrderService orderSvc
                        , IDepartmentService deptSvc
                        , IEmployeeRepository empRep)
   {
      _orderSvc = orderSvc;
      _deptSvc = deptSvc;
      _empRep = empRep;
   }
   //methods down here
}

这实际上通常不是问题,但我想知道为什么不设置我们传递的工厂类呢?

public ServiceFactory
{
   virtual IEmployeeService GetEmployeeService();
   virtual IDepartmentService GetDepartmentService();
   virtual IOrderService GetOrderService();
}

然后而不是打电话:

_orderSvc.CalcOrderTotal(orderId) 
我们打电话给

_svcFactory.GetOrderService.CalcOrderTotal(orderid)

这种方法的缺点是什么?它仍然可以测试,它仍然允许我们使用D.I. (并通过工厂内外的D.I.处理外部依赖关系,如数据库上下文和电子邮件发件人),它消除了很多D.I.更多地设置和整合依赖项。

感谢您的想法!

3 个答案:

答案 0 :(得分:4)

反对此的一个论点是它不会使您的依赖关系变得清晰。它表明你依赖“服务工厂中的一些东西”但不依赖于哪些服务。对于重构目的,确切地知道什么取决于什么是有帮助的。

依赖注入应该使这种事情变得容易,如果你使用了一个合适的框架 - 它应该只是创建正确的构造函数,定义实现哪个接口,并让它解决所有问题。

答案 1 :(得分:3)

这样的工厂本质上是服务定位器I consider it an anti-pattern,因为它模糊了您的依赖关系,并且很容易违反Single Responsibility Principle(SRP)。

我们从构造函数注入中获得的众多优势之一就是it makes violations of the SRP so glaringly obvious

答案 2 :(得分:2)

如果你的大多数类依赖于这三个接口,你可以传递一个将它们包装在一起的对象,但是:如果大多数类只依赖于其中的一个或两个,那么这不是一个好主意,因为这些类将具有访问他们不需要的对象,他们没有业务,一些程序员总是会调用他们不应该调用的代码,因为它可用。

顺便说一句,它不是工厂,除非你总是在Get [...] Service()方法中创建一个新对象,并且这样做只是为了传递一些方法是不好的。我只是将它称为ServiceWrapper并将它们转换为EmployeeService,DepartmentService和OrderService属性。