Вместо того, чтобы рассказывать всю теорию о IOC / DI, я подумал объяснить на примере.
Требование: Мы получим некоторый адрес клиента, и нам нужно подтвердить адрес.
После некоторой оценки мы подумали об использовании службы проверки адресов Google.
Устаревший (плохой) подход:
Просто создайте класс AddressVerificationService и реализуйте логику.
Предположим, GoogleAddressVerificationService — это сервис, предоставляемый Google, который принимает адрес в качестве строки и возвращает долготу / широту.
1
2
3
4
5
6
7
8
9
|
class AddressVerificationService { public String validateAddress(String address) { GoogleAddressVerificationService gavs = new GoogleAddressVerificationService(); String result = gavs.validateAddress(address); return result; } } |
Проблемы с этим подходом:
1. Если вы хотите изменить своего поставщика услуг проверки адреса, вам нужно изменить логику.
2. Вы не можете выполнить модульное тестирование с помощью некоторого фиктивного AddressVerificationService (используя фиктивные объекты)
По какой-то причине Клиент просит нас поддержать нескольких провайдеров AddressVerificationService, и мы должны определить, какую службу использовать во время выполнения.
Для этого вы можете подумать об изменении вышеуказанного класса, как показано ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
class AddressVerificationService { //This method validates the given address and return longitude/latitude details. public String validateAddress(String address) { String result = null ; int serviceCode = 2 ; // read this code value from a config file if (serviceCode == 1 ) { GoogleAddressVerificationService googleAVS = new GoogleAddressVerificationService(); result = googleAVS.validateAddress(address); } else if (serviceCode == 2 ) { YahooAddressVerificationService yahooAVS = new YahooAddressVerificationService(); result = yahooAVS.validateAddress(address); } return result; } } |
Проблемы с этим подходом:
1. Всякий раз, когда вам нужно поддержать нового поставщика услуг, вам нужно добавить / изменить логику, используя if-else-if.
2. Вы не можете выполнить модульное тестирование с помощью некоторого фиктивного AddressVerificationService (используя фиктивные объекты)
Подход IOC / DI:
В вышеупомянутых подходах AddressVerificationService берет на себя управление созданием своих зависимостей.
Таким образом, всякий раз, когда происходит изменение в его зависимостях, AddressVerificationService будет меняться.
Теперь давайте перепишем AddressVerificationService с использованием шаблона IOC / DI.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
class AddressVerificationService { private AddressVerificationServiceProvider serviceProvider; public AddressVerificationService(AddressVerificationServiceProvider serviceProvider) { this .serviceProvider = serviceProvider; } public String validateAddress(String address) { return this .serviceProvider.validateAddress(address); } } interface AddressVerificationServiceProvider { public String validateAddress(String address); } |
Здесь мы внедряем зависимость AddressVerificationService AddressVerificationServiceProvider.
Теперь давайте реализуем AddressVerificationServiceProvider с несколькими сервисами провайдера.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
class YahooAVS implements AddressVerificationServiceProvider { @Override public String validateAddress(String address) { System.out.println( "Verifying address using YAHOO AddressVerificationService" ); return yahooAVSAPI.validate(address); } } class GoogleAVS implements AddressVerificationServiceProvider { @Override public String validateAddress(String address) { System.out.println( "Verifying address using Google AddressVerificationService" ); return googleAVSAPI.validate(address); } } |
Теперь Клиент может выбрать, какой сервис Поставщика услуг использовать следующим образом:
1
2
3
4
5
6
7
8
|
AddressVerificationService verificationService = null ; AddressVerificationServiceProvider provider = null ; provider = new YahooAVS(); //to use YAHOO AVS provider = new GoogleAVS(); //to use Google AVS verificationService = new AddressVerificationService(provider); String lnl = verificationService.validateAddress( "HitechCity, Hyderabad" ); System.out.println(lnl); |
Для модульного тестирования мы можем реализовать Mock AddressVerificationServiceProvider.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
class MockAVS implements AddressVerificationServiceProvider { @Override public String validateAddress(String address) { System.out.println( "Verifying address using MOCK AddressVerificationService" ); return "<response><longitude>123</longitude><latitude>4567</latitude>" ; } } AddressVerificationServiceProvider provider = null ; provider = new MockAVS(); //to use MOCK AVS AddressVerificationServiceIOC verificationService = new AddressVerificationServiceIOC(provider); String lnl = verificationService.validateAddress( "Somajiguda, Hyderabad" ); System.out.println(lnl); |
С этим подходом мы перечислили проблемы с вышеупомянутыми подходами, не основанными на МОК / DI
1. Мы можем предоставить поддержку для любого количества провайдеров, сколько пожелаем. Просто внедрите AddressVerificationServiceProvider и вставьте его.
2. Мы можем выполнить модульное тестирование, используя фиктивные данные, используя Mock.
Таким образом, следуя принципу внедрения зависимостей, мы можем создавать слабосвязанные и легко тестируемые сервисы на основе интерфейса.
Ссылка: Как я объяснил инъекцию зависимостей в мою команду от нашего партнера по JCG Сивы Редди в блоге « Мои эксперименты по технологии» .