对不起C#
是我所选择的语言,我可以读Java
,但可能会杀猪的语法试图写它...相同的概念之间适用C#
和Java
的,所以希望这将显示你如何能逐渐将你的代码库更加的步骤可测试的。
鉴于:
public class MyUI
{
public void SomeMethod()
{
Foo foo = new Foo();
foo.DoStuff();
}
}
public class Foo
{
public void DoStuff()
{
Bar bar = new Bar();
bar.DoSomethingElse();
}
}
public class Bar
{
public void DoSomethingElse();
}
可以很容易地重构为使用DI,而无需使用IOC容器-您甚至可能将其分解为几个步骤:
(可能)第一步-引入依赖关系,但不更改调用(UI)代码:
public class MyUI
{
public void SomeMethod()
{
Foo foo = new Foo();
foo.DoStuff();
}
}
public class Foo
{
private IBar _iBar;
// Leaving this constructor for step one,
// so that calling code can stay as is without impact
public Foo()
{
_iBar = new Bar();
}
// simply because we now have a constructor that take's in the implementation of the IBar dependency,
// Foo can be much more easily tested.
public Foo(IBar iBar)
{
_iBar = iBar;
}
public void DoStuff()
{
_iBar.DoSomethingElse();
}
}
public interface IBar
{
void DoSomethingElse();
}
public class Bar
{
public void DoSomethingElse();
}
重构2(或首先重构,如果实现IOC容器并立即更改调用代码):
public class MyUI
{
public void SomeMethod()
{
Foo foo = null // use your IOC container to resolve the dependency
foo.DoStuff();
}
}
public class Foo
{
private IBar _iBar;
// note we have now dropped the "default constructor" - this is now a breaking change as far as the UI is concerned.
// You can either do this all at once (do only step 2) or in a gradual manner (step 1, then step 2)
// Only entry into class - requires passing in of class dependencies (IBar)
public Foo(IBar iBar)
{
_iBar = iBar;
}
public void DoStuff()
{
_iBar.DoSomethingElse();
}
}
从技术上讲,步骤2可以自己完成-但(可能)要做很多工作-取决于当前有多少类正在“更新”您要寻找DI的功能。
考虑使用第1步->第2步路线-您可以创建Foo
独立于的单元测试Bar
。而在步骤1重构之前,如果不使用这两个类的实际实现就很难完成它。执行步骤1->步骤2(而不是立即执行步骤2)将允许随着时间的推移进行较小的更改,并且您已经开始使用测试工具,以便更好地确保重构工作不会产生任何后果。