Внедрение зависимостей (DI) - это один из шаблонов проектирования, в котором используется основная функция ООП - связь одного объекта с другим объектом. В то время как наследование наследует один объект, чтобы сделать более сложный и конкретный другой объект, связь или ассоциация просто создает указатель на другой объект из одного объекта, используя атрибут. Мощность DI сочетается с другими функциями ООП, такими как интерфейсы и скрытый код.
Предположим, у нас есть клиент (подписчик) в библиотеке, который может заимствовать только одну книгу для простоты.
Интерфейс книги:
package com.deepam.hidden;
public interface BookInterface {
public BookInterface setHeight(int height);
public BookInterface setPages(int pages);
public int getHeight();
public int getPages();
public String toString();
}
Далее у нас может быть много разных книг; один из типов это художественная литература:
package com.deepam.hidden;
public class FictionBook implements BookInterface {
int height = 0; // height in cm
int pages = 0; // number of pages
/** constructor */
public FictionBook() {
// TODO Auto-generated constructor stub
}
@Override
public FictionBook setHeight(int height) {
this.height = height;
return this;
}
@Override
public FictionBook setPages(int pages) {
this.pages = pages;
return this;
}
@Override
public int getHeight() {
// TODO Auto-generated method stub
return height;
}
@Override
public int getPages() {
// TODO Auto-generated method stub
return pages;
}
@Override
public String toString(){
return ("height: " + height + ", " + "pages: " + pages);
}
}
Теперь у подписчика может быть ассоциация с книгой:
package com.deepam.hidden;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Subscriber {
BookInterface book;
/** constructor*/
public Subscriber() {
// TODO Auto-generated constructor stub
}
// injection I
public void setBook(BookInterface book) {
this.book = book;
}
// injection II
public BookInterface setBook(String bookName) {
try {
Class<?> cl = Class.forName(bookName);
Constructor<?> constructor = cl.getConstructor(); // use it for parameters in constructor
BookInterface book = (BookInterface) constructor.newInstance();
//book = (BookInterface) Class.forName(bookName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return book;
}
public BookInterface getBook() {
return book;
}
public static void main(String[] args) {
}
}
Все три класса могут быть скрыты для собственной реализации. Теперь мы можем использовать этот код для DI:
package com.deepam.implement;
import com.deepam.hidden.Subscriber;
import com.deepam.hidden.FictionBook;
public class CallHiddenImplBook {
public CallHiddenImplBook() {
// TODO Auto-generated constructor stub
}
public void doIt() {
Subscriber ab = new Subscriber();
// injection I
FictionBook bookI = new FictionBook();
bookI.setHeight(30); // cm
bookI.setPages(250);
ab.setBook(bookI); // inject
System.out.println("injection I " + ab.getBook().toString());
// injection II
FictionBook bookII = ((FictionBook) ab.setBook("com.deepam.hidden.FictionBook")).setHeight(5).setPages(108); // inject and set
System.out.println("injection II " + ab.getBook().toString());
}
public static void main(String[] args) {
CallHiddenImplBook kh = new CallHiddenImplBook();
kh.doIt();
}
}
Существует много разных способов использования внедрения зависимостей. Можно комбинировать его с Singleton и т. Д., Но все же в основном это только ассоциация, реализованная путем создания атрибута типа объекта внутри другого объекта.
Полезность только и только в том, что код, который мы должны писать снова и снова, всегда готов и сделан для нас вперед. Вот почему DI так тесно связан с Inversion of Control (IoC), что означает, что наша программа передает управление другому работающему модулю, который делает инъекции bean-компонентов в наш код. (Каждый объект, который может быть введен, может быть подписан или рассматриваться как Бин.) Например, в Spring это делается путем создания и инициализации контейнера ApplicationContext , который выполняет эту работу за нас. Мы просто в нашем коде создаем Context и вызываем инициализацию bean-компонентов. В этот момент инъекция была сделана автоматически.