У меня чаще всего возникает соблазн использовать "инъекцию ублюдка" в некоторых случаях.Когда у меня есть «правильный» конструктор внедрения зависимостей:
public class ThingMaker {
...
public ThingMaker(IThingSource source){
_source = source;
}
Но тогда для классов, которые я собираюсь использовать как публичные API (классы, которые будут использовать другие команды разработчиков), я могуникогда не находите лучший вариант, чем писать «ублюдочный» конструктор по умолчанию с наиболее вероятной необходимой зависимостью:
public ThingMaker() : this(new DefaultThingSource()) {}
...
}
Очевидным недостатком здесь является то, что это создает статическую зависимость от DefaultThingSource;в идеале такой зависимости не было бы, и потребитель всегда вводил бы любой IThingSource, который он хотел.Однако это слишком сложно для использования;потребители хотят создать ThingMaker и приступить к созданию вещей, а спустя несколько месяцев, когда возникнет такая необходимость, внедрить что-то еще.Это оставляет всего несколько вариантов на мой взгляд:
- Пропустить ублюдочный конструктор;заставить потребителя ThingMaker понять IThingSource, понять, как ThingMaker взаимодействует с IThingSource, найти или написать конкретный класс, а затем внедрить экземпляр в вызов их конструктора.
- Пропустите конструктор-ублюдок и предоставьте отдельную фабрику, контейнер или другой класс / метод начальной загрузки;каким-то образом заставить потребителя понять, что ему не нужно писать собственный IThingSource;вынудите потребителя ThingMaker найти и понять фабрику или загрузчик и использовать ее.
- Сохраните ублюдочный конструктор, позволяя потребителю «создавать» новый объект и запускать его, а также справляться с необязательной статической зависимостьюна DefaultThingSource.
Мальчик, # 3, конечно, кажется привлекательным.Есть ли другой, лучший вариант?Кажется, что № 1 или № 2 того не стоят.