如果您使用的接口或至少抽象/可继承类,你可以通过执行中的DI/IoC的配置容易交换(注入另一个类)更改程序的行为。 使用接口是一种很好的做法(imho)。如果你正在编写需要模拟的UnitTests,这一点尤其重要。如果你不使用接口,编写UnitTests的覆盖面很难(在大多数“现实世界”情况下不能说是不可能的)。
我想你应该使用的接口,如果有可能是一个机会,注入部分可能会改变。应该很容易扩展您的实现,请参见Open-Closed-Principle。 =>这将需要交换模块/部件/实现......问问自己如果你的类没有虚拟函数来覆盖会发生什么,你不得不改变实现。
我会使用接口至少为公共类 /您的代码的一部分(其他程序员将使用的部分)。
在看看你的样品。 问题出在接线部分,而不仅仅是绑定作为接口的(默认)实现(绑定工作,但接线可能会中断)。
例如,如果你有2个实现(这里的C#示例,在Java中应该是相同的。,太):
public interface IUserStorage
{
void Write(object something);
}
public class UserStorageTextFile : IUserStorage
{
public void Write(object something) { ... }; // stores to text file
}
public class UserStorageDB : IUserStorage
{
public void Write(object something) { ... }; // stores to DB
}
public class MyStorageClient
{
public MyStorageClient(IUserStorage storage) { ... } // copy to private field and use it etc.
}
取决于你的IoC它应该很容易接线 MyStorageClient的实例来你IUserStorage结合。
bind(IUserStorage.class).to(UserStorageDB.class); // Java sample, eh?
但如果你MyStorageClient强烈被迫使用DB已经...
public class MyStorageClient
{
public MyStorageClient(UserStorageDB storage) { ... } // copy to private field and use it etc.
}
...这是IMPOSIBLE与除UserStorageTextFile的UserStorageTextFile类是从UserStorageDB继承接线起来。 ..但为什么你应该有一个依赖于例如如果你只想写一个简单的文本文件,Oracle驱动程序(UserStorageDB需要)?
我认为样本不够清晰,显示了使用接口的好处...
,但如果没有...尝试这样做:基于
bind(UserStorageDB.class).to(UserStorageTextFile.class);
// and in another config/module/unitTest
bind(UserStorageTextFile.class).to(Mock(UserStorageDB.class));
// and try to wire it against your client class, too (both ways, meaning one config for TextFile and load a config for the DB after changing only the configuration)
请不要为每个容器管理的依赖项创建一个接口,除非有一些令人信服的理由。如果需要,稍后可以很容易地将类重构为接口。 –
@aryaxt:为什么要创建/使用一个接口破解OOP原则。你能举一个例子/报价吗? – Beachwalker
@ default.kramer:只有拥有/维护代码并且可以更改代码才是简单的。与具有虚拟功能(甚至密封)的类相比,使用接口更符合开放 - 关闭原则。 – Beachwalker