2012-06-03 3 views
3

Я пытаюсь понять зависимость впрыска, и я добился прогресса, ноInjection Dependency Injection - в чем разница между этими двумя кодами?

Мне будет интересно узнать о преимуществах/различиях/важности этого кода. Они выглядят одинаково, но другой подход

//dependency injection - (as was claimed) 
Customer customer = new Customer(10); 

IOrderDAO orderDAO = new OrderDAO(); 
customer.setOrderDAO(orderDAO); 
customer.getOrdersByDate(); 

ИЛИ

//Unknown Pattern - Please what pattern is this? 
Customer customer = new Customer(10); 
IOrderDAO orderDAO = new OrderDAO(); 
orderDAO.getOrderByDate(customer.id); 

Что случилось со вторым подходом?

Спасибо.

+1

В этом нет ничего плохого. – bmargulies

+0

Я думаю, что есть разница - см. Ниже. – duffymo

+0

Я не сказал, что не было никакой разницы. – bmargulies

ответ

3

Ни один из нас не выглядит как инъекция зависимостей; не должно быть вызовов new.

Зависимость инъекции осуществляется фабрикой фасоли, которая подключена ко всем зависимостям. Он создает экземпляры боба и дает им свои зависимости.

Я вообще не вижу фабрику фасоли. Это долгий путь к инъекции зависимостей.

Клиент получает OrderDAO в первом примере, используя установщик. В первом говорится, что Клиент должен раскрывать методы сохранения в своем API. Он несет ответственность за сохранение своих ордеров. Я бы сказал, что это плохое разделение проблем, потому что теперь клиенты должны знать о Заказе.

Второй хранит Заказчика отдельно от OrderDAO. Вы передаете идентификатор клиента в OrderDAO и сохраняете его заказы от имени этого клиента. Я думаю, что это лучшее разделение проблем.

Но ни один из них не является хорошим примером инъекции зависимости.

Первое и лучшее описание DI произошло от Martin Fowler. Я рекомендовал бы, чтобы вы это внимательно прочитать:

http://martinfowler.com/articles/injection.html

Это восемь лет, но до сих пор на месте.

+0

Инъекционная инъекция не требует контейнера - это просто означает, что классы не несут ответственности за создание или обнаружение их зависимостей. – Lee

+0

Не требует, но каждый пример, который я могу представить, имеет один: PicoContainer, Spring, Guice. Кроме того, мои пункты имеют меньше общего с DI и все, что связано с разделением проблем. – duffymo

+0

Просьба показать код. Просто зарисуйте несколько комментариев, я выберу его оттуда. Зависимость Инъекция была загадкой до вчерашнего дня, что у меня было лучшее понимание, и, как вы видите, я все еще запутался. – codingbiz

3

Ни один из них не является надлежащим примером инъекции зависимости. Это скорее примеры шаблонов доступа к данным.

Первый пример - active record pattern. Установив orderDAO в качестве зависимости для субъекта клиента, мы могли бы назвать свойство или инет.

Вторым примером может быть repository pattern.. Образец зависимостей здесь будет методом инъекции, который переводится в общий метод вызова с некоторыми параметрами (здесь параметры являются зависимостями для метода).

Хороший способ начать обучение шаблону ДИ будет читать this book.Есть также много интернет-ресурсов, как эти видео:

Я бы также рекомендовал ищет Dependency Inversion принцип в гугле (it's not the same as dependency injecion).

1

Это нечетный пример, но первый демонстрирует , что инъекция контейнер зависимости будет делать, а второй демонстрирует один объект, проходящего аргумент к другому объекту. Первый вставляет свои зависимости в качестве переменных экземпляра вызывающего класса; второй - более процедурный по своей природе. Также нет неправильный, 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 (здесь не показано ради краткости).

В этом смысл?

+0

хорошо принят. но не должен __service.setDao (service) __ be ** service.setDao (dao) ** – codingbiz

+0

Хороший улов. Я исправлю это. –

1

Не путайте инверсию управления с инъекцией зависимостей (как еще один ответ).Я описываю зависимость инъекции и IoC здесь: http://www.codeproject.com/Articles/386164/Get-injected-into-the-world-of-inverted-dependenci

//dependency injection - (as was claimed) 
Customer customer = new Customer(10); 

IOrderDAO orderDAO = new OrderDAO(); 
customer.setOrderDAO(orderDAO); 
customer.getOrdersByDate(); 

Нет, я бы не назвал, что DI. Я бы назвал это плохо написанным кодом. Заказчик не должен знать о уровне прочности, который setOrderDAO(orderDAO) заставляет его действовать. Это нарушает принцип единой ответственности, так как клиент также должен заботиться о заказах.

//Unknown Pattern - Please what pattern is this? 
Customer customer = new Customer(10); 
IOrderDAO orderDAO = new OrderDAO(); 
orderDAO.getOrderByDate(customer.id); 

Это не конкретный шаблон, но лучше код, так как не существует связь между customer и orderDao.

Смежные вопросы