Резюме

Паттерны, представленные в этой главе, являются центральной частью DI. Вооружившись Composition Root и соответствующим набором DI паттернов, вы можете реализовать основы DI. При применении DI есть много нюансов и мелких деталей, которые нужно выучить, но паттерны покрывают основную механику, которая отвечает на вопрос: как я могу внедрить зависимости?

Эти паттерны не являются взаимозаменяемыми. В большинстве случаев вашим первым выбором должно быть внедрение в конструктор, но бывают ситуации, когда один из других паттернов является лучшей альтернативой. Рисунок 4-12 показывает процесс принятия решений, который может помочь вам принять решение о выборе нужного паттерна, но если есть сомнения, выберите внедрение в конструктор: вы никогда сильно не ошибетесь в этом выборе.

Рисунок 4-12: В большинстве случаев вы должны выбирать внедрение в конструктор, но бывают ситуации, когда один из других DI паттернов подходит лучше.

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

Когда зависимость представляет Cross-Cutting Concern, выбор подходящего паттерна зависит от направления коммуникации. Если вам нужно только что-нибудь записать (например, время, которое заняла операция, или то, какие значения передаются), лучшей альтернативой является перехват (о котором я расскажу в главе 9). Он также хорошо работает, если ответ, который вам нужен от него, уже включен в определение интерфейса. Кэширование является прекрасным примером этого использования перехвата.

Если вам необходимо запросить Cross-Cutting зависимость для ответа, который не включен в оригинальный интерфейс, вы можете использовать Ambient Context, только если у вас есть надлежащая Local Default, которая позволяет оформить сам контекст разумным поведением по умолчанию, которое работает для всех клиентов без явной настройки.

Когда зависимость не представляет Cross-Cutting Concern, Local Default все еще является решающим фактором, поскольку она может сделать явное внедрение зависимости необязательным – используется реализация по умолчанию, если не указана переопределяющая реализация. Этот сценарий может быть эффективно использован при помощи внедрения в свойство.

В любых других случаях применяется паттерн внедрения в конструктор. Исходя из рисунка 4-12, кажется, что внедрение в конструктор является последним оплотом, который входит в игру только тогда, когда все остальное не дает результатов. Это верно лишь отчасти, поскольку в большинстве случаев специализированные паттерны не применяются, и по умолчанию на поле остается внедрение в конструктор. Его легче понять и проще надежно реализовать, чем любой из других DI паттернов. Вы можете построить целые приложения только с одним внедрением в конструктор, но понимание других паттернов может помочь вам в разумном выборе нужного в некоторых случаях, когда он не подходит.

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

или RSS канал: Что новенького на smarly.net