检查以下简化示例代码:
public class RequestManager
{
public RequestManager()
{
}
public void ProcessRequest(byte[] data)
{
IRequest request = new Request(data);
request.Send();
}
}
当我发现自己使用此代码进行测试时,我结束了:
public class RequestManager
{
private IRequestFactory requestFactory;
public RequestManager(IRequestFactory requestFactory)
{
this.requestFactory = requestFactory;
}
public void ProcessRequest(byte[] data)
{
IRequest request = this.requestFactory.CreateRequest(data);
request.Send();
}
}
CreateRequest方法只有新的Request(数据),所以我可以模拟工厂并返回一个模拟。
问题是我开始有很多工厂来完成如此简单的任务,我想知道这是否正常,或者是否有一种模式或其他方法可以帮助我解决这个问题。
有什么想法吗?提前谢谢。
答案 0 :(得分:2)
这不仅是正常的,而且也是体面设计的标志。在正确应用DI的应用程序中,您不需要工厂:
对于其他一切,工厂是一个不错的选择。为什么呢?
IRequest
实例时,你应该注入IRequestFactory
)SomeProperty
吗?”或“我使用哪种构造函数?。{ {1}}是微不足道和直观的 - 不需要解释任何事情,所有的决定都已经制定并嵌入工厂本身了。)除了单元测试之外,当您在3个月,6个月,12个月内返回代码时,前两个点会带来极大的好处 - 工厂 减轻开发人员做出决策关于东西这不应该要求首先作出任何决定。
而不是想知道使用哪个构造函数和传递什么参数,你有一个非常简单的合同来回答所有可能的问题,而你作为一个开发人员,可以专注于实际问题。
答案 1 :(得分:1)
IRequest request = new Request(data);
这条线与Dependancy Injection完全相反。它是一种硬编码的依赖。此行将RequestManager
类与Request
的{{1}}实现绑定在一起。
也许试试这个:
IRequest
这样,public void ProcessRequest(IRequest request)
{
request.Send();
}
不必具有任何IRequest实现的知识。你可以把它变成一个模拟对象/存根,它甚至不会感觉到什么!当然,这意味着创建其RequestManager
的类需要知道该依赖性。但是,嘿,你可以用类似的方式将它RequestManager
交给它!
最后,所有依赖关注点都集中在一个点上。通常我们使用一些框架来为我们处理连接事务,例如基于XML文件。
依赖性的全部意义在于通过setter或构造函数参数提供所需的具体对象。依赖注入框架允许您将依赖项集中在一个位置,从中您可以轻松地将提供的具体类更改为需要它们的其他类。这样你就可以在测试中使用模拟对象进行设置 - 非常方便!
Here你可以找到一篇关于依赖性注射的精彩文章