Почему бы не разбить все классы обслуживания на метод Factory (вместо ввода интерфейсов)?

Мы строим проект ASP.NET и инкапсулируем всю нашу бизнес-логику в классы обслуживания. Некоторые из них находятся в объектах домена, но обычно они довольно анемичны (из-за используемой нами ORM, которая не изменится). Чтобы лучше включить модульное тестирование, мы определяем интерфейсы для каждой службы и используем D.I.. например. вот пара интерфейсов:

IEmployeeService
IDepartmentService
IOrderService
...

Все методы этих служб - это в основном группы задач, а классы не содержат частных переменных-членов (кроме ссылок на зависимые службы). Прежде чем мы будем беспокоиться об Unit Testing, мы просто объявим все эти классы статическими и попросим их напрямую позвонить друг другу. Теперь мы настроим такой класс, если услуга зависит от других сервисов:

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
}

Это действительно не проблема, но мне интересно, почему бы не создать класс factory, который мы передаем вместо этого?

то есть.

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

Затем вместо вызова:

_orderSvc.CalcOrderTotal(orderId) 

мы бы назвали

_svcFactory.GetOrderService.CalcOrderTotal(orderid)

Какое падение этого метода? Он все еще проверяется, он все же позволяет нам использовать D.I. (и обрабатывать внешние зависимости, такие как контексты базы данных и отправители электронной почты через D.I. внутри и вне factory), и устраняет много D.I. настройка и консолидация зависимостей больше.

Спасибо за ваши мысли!

Ответ 1

Если большинство ваших классов зависят от этих трех интерфейсов, вы можете передать объект, который обертывает их вместе, НО: если большинство классов просто зависят от одного или двух из них, то это не очень хорошая идея, поскольку эти классы будут иметь доступ к объектам, которые им не нужны, и у них нет бизнеса, и некоторые программисты всегда будут вызывать код, который они не должны вызывать, просто потому, что он доступен.

Btw, это не factory, если вы не всегда создаете новый объект в методах Get [...] Service(), и делать это просто для прохождения нескольких методов вокруг - это плохо. Я бы назвал это ServiceWrapper и превратил их в свойства EmployeeService, DepartmentService и OrderService.

Ответ 2

Один аргумент против этого состоит в том, что он не делает ваши зависимости ясными. Это показывает, что вы зависите от "некоторых вещей в сервисе factory", но не для каких служб. Для целей рефакторинга полезно знать, что от этого зависит.

Включение зависимостей должно сделать это проще, если вы используете подходящую фреймворк - это просто вопрос создания правильного конструктора, определения того, что реализует этот интерфейс, и позволить ему разобраться во всем.

Ответ 3

Такой factory по существу является Service Locator, а Я считаю это анти-шаблоном, потому что это заслоняет ваши зависимости и позволяет легко нарушить принцип единой ответственности (SRP).

Одним из многих превосходных преимуществ, которые мы получаем от Инъекции конструктора, является то, что делает нарушения SRP настолько очевидными..