Почему бы не разбить все классы обслуживания на метод 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 настолько очевидными..