Внедрение зависимостей, как практика, предназначено для введения абстракций (или швы ) для отделения изменчивых зависимостей. Энергозависимая зависимость - это класс или модуль, который, среди прочего, может содержать недетерминированное поведение или вообще является чем-то, что мы можем заменить или перехватить. Для более подробного обсуждения изменчивых зависимостей см. раздел 1.3.2 этого свободно загружаемого введения из этой книги .
Поскольку ваш FileLogger
записывает на диск, он содержит недетерминированное поведение . По этой причине вы ввели абстракцию ILoggable
. Это позволяет отделить потребителей от реализации FileLogger
.
Однако, чтобы иметь возможность успешно отделить потребителя от его изменчивой зависимости, нам необходимо внедрить эту зависимость в потребителя. На выбор предлагается три общих шаблона:
- Внедрение в конструктор - Зависимости статически определяются как список параметров для конструктора instance класса.
- Внедрение свойства - Зависимости вводятся в потребителя через свойства instance , доступные для записи.
- Внедрение метода - Зависимости вводятся в потребителя как параметры метода.
И Инъекция конструктора, и Инъекция свойства применяются внутри Корень композиции и требуют от потребителя сохранить зависимость в закрытом поле для последующего повторного использования. Для этого необходимо, чтобы конструктор и свойство были членами экземпляра , то есть нестатическими. Статические конструкторы не могут иметь никаких параметров, а статические свойства приводят к анти-шаблону Ambient Context (см. Главу 5.3 этой книги ) и Temporal Coupling . Это затрудняет тестируемость и ремонтопригодность.
Внедрение метода, с другой стороны, применяется вне корня композиции, и оно не сохраняет любую предоставленную зависимость, а просто использует ее. Поэтому внедрение метода может применяться как к экземпляру, так и к статическим методам. В этом случае потребитель метода должен предоставить зависимость. Это, однако, означает, что сама эта зависимость должна быть предоставлена либо с помощью внедрения конструктора, свойства или метода.
Ваш пример статического LogService
, который создал FileLogger
внутри его конструктора, является отличным примером сильно связанного кода. Это называется анти-паттерном Control Freak (глава 5.1) или вообще может рассматриваться как нарушение DIP . Это напротив DI.
Чтобы предотвратить сильное связывание энергозависимых зависимостей, лучше всего сделать LogService
нестатичным и внедрить его энергозависимые зависимости в единственный открытый конструктор.