代码之家  ›  专栏  ›  技术社区  ›  Andrew

为什么不将所有服务类都合并到工厂方法中(而不是注入接口)?

  •  11
  • Andrew  · 技术社区  · 15 年前

    我们正在构建一个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 回复  |  直到 15 年前
        1
  •  2
  •   Morfildur    15 年前

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

    顺便说一句,除非您总是在get[…]service()方法中创建一个新的对象,并且仅仅为了传递几个方法而这样做是不好的,否则它不是一个工厂。我将其称为ServiceWrapper,并将其转换为EmployeeService、DepartmentService和OrderService属性。

        2
  •  4
  •   Jon Skeet    15 年前

    反对这一点的一个理由是,它不能使您的依赖性变得清晰。这表明你依赖于“服务工厂里的一些东西”,而不是什么服务。为了重构的目的,确切地知道什么取决于什么可能是有帮助的。

    依赖注入 应该 如果您使用的是适当的框架,那么让这类事情变得简单——应该只需要创建正确的构造函数,定义实现哪个接口的内容,并让它对所有内容进行排序。

        3
  •  3
  •   Mark Seemann    15 年前

    这样的工厂本质上是 服务定位器 I consider it an anti-pattern 因为它掩盖了你的依赖性,使你很容易违反 Single Responsibility Principle (SRP)。

    我们从中获得的诸多好处之一 构造器注入 那是 it makes violations of the SRP so glaringly obvious .