【发布时间】:2012-02-05 20:58:01
【问题描述】:
这里有一个非常受关注的概念:Ioc(控制反转)。 我使用这个概念已经有一段时间了。通常我会选择 DI(而不是服务定位器)方法在我的代码中实现 IoC。 以下是我对 IoC 的理解。
如果 classA 依赖于 classB,如果它在其中声明了 classB 的实例。它依赖于 B 类,出于某种原因(我稍后会谈到),不好,因此我们使用 DI 来解决这个问题。所以现在我们有一个名为 IClassB 的接口,它将在 classA 的构造函数中传递(为了说明,我在这里使用构造函数注入)。代码如下:
public class ClassA
{
IClassB _classBObj = null;
public ClassA(IClassB classBObj)
{
_classBObj = classBObj;
}
public void UseClassBMethod()
{
this._classBObj.classBMethod();
}
}
public class ClassB:IClassB
{
public void classBMethod()
{
//Some task carried out by classB.
}
}
public interface IClassB
{
void classBMethod();
}
下面是让它运行的代码:
class Program
{
static void Main(string[] args)
{
//This code is outside of class A and hence declaring
//object of ClassB is not dependency
ClassA classA=new ClassA(new ClassB);
classA.UseClassBMethod();
}
}
我演示了上面的示例只是为了确保我对 IoC 和 DI 的理解是否正确。如果您发现任何错误,请纠正我。 现在,当我试图找出 IoC 的原因时,我发现了两个重要原因:
可测试性:当然是一个正确的问题。假设,例如,在上面的例子中,classB 方法使用 SMPTP 服务器或一些 WCF/Web 服务,我们可能无法对其进行测试。但是,我们可以创建一个实现接口 IClassB 的测试存根类,并通过传递一个测试存根类的实例来继续测试。
具体实施方面的依赖性:这是我无法接受的。即使我用以下代码更改了classA的代码:
public class ClassA
{
ClassB _classBObj = null;
public ClassA()
{
_classBObj = new ClassB();
}
public void UseClassBMethod()
{
this._classBObj.classBMethod();
}
}
IoC 如何帮助解决因 ClassB 对象的 classB 方法发生变化而出现的任何问题?如果方法签名有任何变化,我们也必须在接口 IClassB 的方法签名中进行更改(实际上,这增加了重构任务。)。如果方法实现发生更改,例如它占用了额外的日志记录任务,则更改将仅限于 ClassB 代码。
这个问题我可能看起来有点愚蠢,但是有人可以提出一个场景(除了单元可测试性之外)我们从这种方法中受益吗?
非常感谢您阅读本文。
【问题讨论】:
标签: design-patterns architecture dependency-injection inversion-of-control