Внедрение зависимости

Материал из Seo Wiki - Поисковая Оптимизация и Программирование

Перейти к: навигация, поиск

Внедрение зависимости (англ. Dependency injection) обозначает процесс предоставления внешней зависимости программному компоненту и является специфичной формой «обращения контроля (англ. Inversion of control)», где изменение порядка связи является путём получения необходимой зависимости.

Условно, если объекту нужно получить доступ к определенному сервису, объект берет на себя ответственность за доступ к этому сервису: он или получает прямую ссылку на местонахождение сервиса, или обращается к известному «сервис-локатору» и запрашивает ссылку на реализацию определенного типа сервиса. Используя же внедрение зависимости, объект просто предоставляет свойство, которое в состоянии хранить ссылку на нужный тип сервиса; и когда объект создается, ссылка на реализацию нужного типа сервиса автоматически вставляется в это свойство (поле), используя средства среды. Внедрение зависимости более гибко, потому как становится легче создавать альтернативные реализации данного типа сервиса, а потом указывать, какая именно реализация должна быть использована в, например, конфигурационном файле, без изменений в объектах, которые этот сервис используют. Это особенно полезно в юнит-тестировании, потому как вставить реализацию «заглушки» сервиса в тестируемый объект очень просто. С другой стороны, излишнее использование внедрения зависимостей может сделать приложения более сложными и трудными в сопровождении: так как для понимания поведения программы программисту необходимо смотреть не только в исходный код, а еще и в конфигурацию, а конфигурация, как правило, невидима для IDE, которые поддерживают анализ ссылок и рефакторинг, если явно не указана поддержка фреймворков с внедрениями зависимостей.

Содержание

Примеры кода

Представим, что IFoo это общий класс, определяющий свой интерфейс:

 class IFoo(Interface):
       def do_bar():
           "perform bar"
       def do_baz():
           "perform baz"

Также есть несколько реализаций, которые реализуют IFoo по разному:

 class DatabaseFoo(object):
       interface.implements(IFoo)
       def do_bar():
           db.select_bar().execute() # Использовать базу данных, чтобы сделать bar
       def do_baz():
           db.select_baz().run() # Использовать базу данных, чтобы сделать baz
 class PixieDustFoo(object):
       interface.implements(IFoo)
       def do_bar():
           cast_spell("bar") # Магия...
       def do_baz():
           cast_spell("baz") # ...и волшебство
 class EnterpriseFoo(object):
       interface.implements(IFoo)
       def do_bar():
           bar = EnterpriseFactoryObserverFactoryCreator("bar")
           bar.creatify()
           bar.preparify()
           bar.configurise()
           bar.make_award_winning()
           bar.opportunities.leverage()
       def do_baz():
           baz = EnterpriseFactoryObserverFactoryCreator("baz")
           baz.creatify()
           baz.preparify()
           baz.configurise()
           baz.make_award_winning()
           baz.opportunities.leverage()

IFoo определяет только операции, которые доступны в интерфейсе, но не предоставляет никакой их реализации, позволяя другим классам реализовывать методы, в нем определенные (на то он и интерфейс). Поэтому пользователь, желающий использовать функционал IFoo, может использовать любую реализацию, не имея никакого понятия о том, как оно работает, кроме того, что они соответствуют спецификации интерфейса Foo.

 class ImportantClass(object):
       def __init__():
           self.foo = EnterpriseFoo()
       def do_really_important_stuff():
           self.foo.do_bar() # оно ничего не делает!

Хотя, это подрывает весь смысл использования интерфейсов вместо конечных реализаций. Чтобы исправить ситуацию, достаточно предоставить вызывающей стороне возможность указывать ту реализацию IFoo, которую она посчитает нужным:

       def __init__(self, foo):
           self.foo = foo

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

Существующие фреймворки

Реализация внедрения зависимостей существует для различных платформ и языков, включая:

ActionScript

C++

ColdFusion

Java

.NET

PHP4

PHP5

Perl

Python

Ruby

См. также

Внешние ссылки


de:Dependency Injection en:Dependency injection es:Inyección de dependencias fr:Injection de dépendances ja:依存性の注入 pl:Wstrzykiwanie zależności pt:Injeção de dependência

Личные инструменты

Served in 0.077 secs.