単純な(そして長い)質問であり、単純な答えではありません。いくつかのDIフレームワーク(Spring、Guice)を使用して作業することで、他の人が提示した実践のいくつかは、実装がそれほど簡単ではないという結論に達しました。私は本当にこのレベルで立ち往生しているようです。
詳細の一部が失われる可能性がありますが、これをできるだけ単純に提示するようにします。質問が明確になることを願っています。
文字列の検証を担当する単純なクラスであるStringValidatorがあるとします。
package test;
import java.util.ArrayList;
import java.util.List;
public class StringValidator {
private final List<String> stringList;
private final List<String> validationList;
private final List<String> validatedList = new ArrayList<String>();
public StringValidator(final List<String> stringList, final List<String> validationList) {
this.stringList = stringList;
this.validationList = validationList;
}
public void validate() {
for (String currentString : stringList) {
for (String currentValidation : validationList) {
if (currentString.equalsIgnoreCase(currentValidation)) {
validatedList.add(currentString);
}
}
}
}
public List<String> getValidatedList() {
return validatedList;
}
}
依存関係は可能な限り低く、次のような簡単なテストが可能です。
package test;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class StringValidatorTest {
@Test
public void testValidate() throws Exception {
//Before
List<String> stringList = new ArrayList<String>();
stringList.add("FILE1.txt");
stringList.add("FILE2.txt");
final List<String> validationList = new ArrayList<String>();
validationList.add("FILE1.txt");
validationList.add("FILE20.txt");
final StringValidator stringValidator = new StringValidator(stringList, validationList);
//When
stringValidator.validate();
//Then
Assert.assertEquals(1, stringValidator.getValidatedList().size());
Assert.assertEquals("FILE1.txt", stringValidator.getValidatedList().get(0));
}
}
柔軟性をさらに高めたい場合は、List<>の代わりにCollection<>を使用できますが、それは必要ないと仮定しましょう。
リストを作成するクラスは次のとおりです(他のインターフェイス標準を使用)。
package test;
import java.util.List;
public interface Stringable {
List<String> getStringList();
}
package test;
import java.util.ArrayList;
import java.util.List;
public class StringService implements Stringable {
private List<String> stringList = new ArrayList<String>();
public StringService() {
createList();
}
//Simplified
private void createList() {
stringList.add("FILE1.txt");
stringList.add("FILE1.dat");
stringList.add("FILE1.pdf");
stringList.add("FILE1.rdf");
}
@Override
public List<String> getStringList() {
return stringList;
}
}
と:
package test;
import java.util.List;
public interface Validateable {
List<String> getValidationList();
}
package test;
import java.util.ArrayList;
import java.util.List;
public class ValidationService implements Validateable {
private final List<String> validationList = new ArrayList<String>();
public ValidationService() {
createList();
}
//Simplified...
private void createList() {
validationList.add("FILE1.txt");
validationList.add("FILE2.txt");
validationList.add("FILE3.txt");
validationList.add("FILE4.txt");
}
@Override
public List<String> getValidationList() {
return validationList;
}
}
そして、mainメソッドを持つMainクラスがあります。
package test;
import java.util.List;
public class Main {
public static void main(String[] args) {
Validateable validateable = new ValidationService();
final List<String> validationList = validateable.getValidationList();
Stringable stringable = new StringService();
final List<String> stringList = stringable.getStringList();
//DI
StringValidator stringValidator = new StringValidator(stringList, validationList);
stringValidator.validate();
//Result list
final List<String> validatedList = stringValidator.getValidatedList();
}
}
したがって、クラスが実行時に(ユーザーが望むときに)リストを生成するとします。「直接」(静的)バインディングは不可能です。
可能な限り低い結合を提供したい場合は、リストを使用して、validation(StringValidator)の実行に必要なデータを提供します。
ただし、コンテナを使用して「グルーコード」を支援する場合は、2つの「サービス」をStringValidatorに挿入できます。それは正しいデータを提供しますが、カップリングが犠牲になります。また、StringValidatorには、実際に依存関係を呼び出すという追加の責任があります。
そのように委任を使用すると、不要な責任(私が望むものではない)でコードが乱雑になります。
そうしないと、これが機能する方法がわかりません(プロバイダーは正しいリストを提供してくれますが、ここでも依存関係があります)。
より一般的な質問は、DIフレームワークを使用して完全に分離されたアプリケーションを実際に作成する方法はありますか、それともこれはある種の理想ですか?DIフレームワークを使用する状況では、使用しませんか?DIフレームワークは本当に「新しい」ものですか?
ありがとうございました。