如果您使用的接口或至少抽象/可繼承類,你可以通過執行中的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