一个简单(且冗长)的问题,而不是一个简单的答案。使用一些 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));
}
}
如果我们想进一步增加灵活性,我们可以使用 Collection<> 而不是 List<>,但我们假设这不是必需的。
创建列表的类如下(使用任何其他接口标准):
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();
}
}
因此,假设类在运行时(当用户想要时)生成列表。“直接”(静态)绑定是不可能的。
如果我们想提供尽可能低的耦合,我们将使用列表为我们提供运行验证所需的数据(StringValidator)。
但是,如果我们想使用容器来帮助我们使用“胶水代码”,我们可以将两个“服务”注入到 StringValidator 中。这将为我们提供正确的数据,但代价是耦合。此外,StringValidator 将承担实际调用依赖项的额外责任。
如果我以这种方式使用委托,我的代码就会被不需要的责任(不是我想要的)弄得乱七八糟。
如果我不这样做,我看不出有什么方法可以工作(提供者可以为我提供正确的列表,但同样,存在依赖关系)。
更普遍的问题是 - 有没有办法使用 DI 框架实际创建一个完全解耦的应用程序,或者这是某种理想?您在哪些情况下使用 DI 框架,在哪些情况下不使用?DI 框架真的是“新的”吗?
谢谢你。