Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 依赖注入-这两个代码之间的区别是什么?_Oop_Dependency Injection - Fatal编程技术网

Oop 依赖注入-这两个代码之间的区别是什么?

Oop 依赖注入-这两个代码之间的区别是什么?,oop,dependency-injection,Oop,Dependency Injection,我一直在努力理解依赖注入,并且我已经取得了进展,但是 我想知道这些代码的好处/区别/重要性。它们看起来是相同的,但方法不同 //dependency injection - (as was claimed) Customer customer = new Customer(10); IOrderDAO orderDAO = new OrderDAO(); customer.setOrderDAO(orderDAO); customer.getOrdersByDate(); 或 第二种方法有什

我一直在努力理解依赖注入,并且我已经取得了进展,但是

我想知道这些代码的好处/区别/重要性。它们看起来是相同的,但方法不同

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

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

第二种方法有什么问题


谢谢。

在我看来,这两个都不像依赖注入;不应调用
new

依赖项注入由连接所有依赖项的bean工厂完成。它实例化bean并给出它们的依赖项

我看这里根本没有豆子工厂。依赖注入还有很长的路要走

在第一个示例中,客户使用setter获取OrderDAO。第一种说法是,客户必须在其API中公开持久性方法。它负责保存订单。我想说,这是一个很差的关注点分离,因为现在客户必须了解订单

第二种方法将客户与OrderDAO分开。您将客户ID传递给OrderDAO,并让它代表该客户保存订单。我认为这是一个更好的分离关注点

但两者都不是依赖注入的好例子

对DI的第一个也是最好的描述来自Martin Fowler。我建议您仔细阅读以下内容:


它已经有八年历史了,但仍然很成功。

它们都不是合适的依赖注入示例。这些都是数据访问模式的典型例子

第一个是一个例子。将orderDAO设置为客户实体的依赖项,我们可以称之为属性或setter注入

第二个例子可能是依赖关系模式,这里是方法注入,它转换为带有一些参数的公共调用方法(这里的参数是方法的依赖关系)

开始学习DI模式的好方法是阅读。还有许多在线资源,如视频:


我还建议在google()中查找依赖项反转原则。

这是一个奇怪的示例,但第一个示例演示了依赖项注入容器的功能,第二个示例演示了一个对象将参数传递给另一个对象。第一种方法将其依赖项嵌入为调用类的实例变量;第二种更具程序性。从本质上来说,两者都没有错。这取决于依赖项的复杂程度以及管理代码的方式

仅仅看一下您提供的注入器代码,并不清楚您为什么要使用依赖项注入。但是考虑一下一个更复杂(更典型)的例子。

客户服务:

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(默认实现):

StubOrderDAO(存根实现):

在运行时,
CustomerService
的实例不知道使用的是iordardao的哪个实现。这意味着您可以非常轻松地引导CustomerService的单元测试,方法是使用
StubOrderDAO
初始化它(它总是返回硬编码的客户)。同样,您的数据源实现可能会有所不同(模拟数据源或在不同运行时环境中不同的数据源)

因此,用于生产的喷油器可能如下所示:

// 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;
而使用本地(测试)数据源的注入器可能如下所示:

// 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;
集成测试的注入器可能如下所示:

// 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
中进行的任何聚合或业务逻辑处理(为了简洁起见,此处未显示)


这更有意义吗?

不要混淆控制反转和依赖注入(正如另一个答案所做的那样)。我在这里描述依赖注入和IoC:

不,我不会称之为DI。我甚至可以称之为写得很糟糕的代码。客户不应该知道持久性层,
setOrderDAO(orderDAO)
强制它保持一致。它打破了单一责任原则,因为客户也必须处理订单

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

这不是特定的模式,但是更好的代码,因为
客户
订单DAO
之间没有耦合,我认为有区别-见下文。我没有说没有区别。依赖项注入不需要容器-它只是意味着类不负责创建或定位它们的依赖项需要,但我能想到的每个例子都有一个:PicoContainer、Spring、Guice。此外,我的观点与DI无关,而与关注点分离有关。请您展示一些代码。只需略作评论,我将从中挑选。依赖注入一直是个谜,直到昨天,我才有了更好的理解,正如你们所看到的,我仍然很困惑。但是不应该是服务。setDao(服务)就是服务。setDao(服务)很好。我会修好的。