Это нечетный пример, но первый демонстрирует , что инъекция контейнер зависимости будет делать, а второй демонстрирует один объект, проходящего аргумент к другому объекту. Первый вставляет свои зависимости в качестве переменных экземпляра вызывающего класса; второй - более процедурный по своей природе. Также нет неправильный, per se. Это зависит от того, насколько сложны ваши зависимости и как вы хотите управлять кодом.
Глядя на код инжектора, который вы указали, не сразу видно, почему вы когда-либо хотели использовать инъекцию зависимостей. Но рассмотрим более сложный (и более типичный) пример на мгновение.
CustomerService:
public class CustomerService implements ICustomerService {
private IOrderDAO orderDao;
public void setOrderDAO(IOrderDAO orderDao) {
this.orderDao = orderDao;
}
public Order getOrderByDate(Integer customerId, Date date) {
return this.orderDao.findOrderByDate(customerId, date);
}
}
OrderDAO (реализация по умолчанию):
public OrderDAO implements IOrderDAO {
private javax.sql.DataSource dataSource;
public void setDataSource(javax.sql.DataSource dataSource) {
this.dataSource = dataSource;
}
public Order findOrderByDate(Integer customerId, Date date) {
...
}
}
StubOrderDAO (реализация заглушки):
public StubOrderDAO implements IOrderDAO {
public Order findOrderByDate(Integer customerId, Date date) {
return new HardCodedOrder(); // this class would extend or implement Order
}
}
Во время выполнения экземпляры CustomerService
не будет иметь какой-либо идея, реализация которой IOrderDAO используется. Это означает, что вы можете очень легко, например, загрузить исходный блок для CustomerService, инициализируя его StubOrderDAO
(который всегда возвращает жестко запрограммированного клиента). Аналогично, ваша реализация DataSource может различаться (либо макет источника данных, либо другой, который отличается в разных средах исполнения).
Так инжектор, предназначенный для использования в производстве может выглядеть так:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = jndiContext.lookup("java:comp/env/MyDataSource");
// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;
Принимая во внимание, инжектор для использования локального (тест) источник данных может выглядеть следующим образом:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = new DriverManagerDataSource("jdbc:sqlserver:yadayada...", "myUsername", "myPassword");
// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;
И инжектор в интеграционный тест может выглядеть так:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new StubOrderDAO();
// initialize
service.setOrderDAO(dao);
return service;
Таким образом, это по существу способ реализовать хорошие расслоение и разделение проблем, то есть способ доступа к базе данных не зависит от того, как вы получаете доступ к данным для создания модели домена, и оба они не зависят от какой-либо обработки агрегирования или бизнес-логики, которую вы бы сделали в CustomerService
(здесь не показано ради краткости).
В этом смысл?
В этом нет ничего плохого. – bmargulies
Я думаю, что есть разница - см. Ниже. – duffymo
Я не сказал, что не было никакой разницы. – bmargulies