在Java中编写无可选参数的可测试代码的正确方法与ABAPOO中的注入
如果我想用Java编写可测试代码,并决定使用依赖项注入模式,以便能够在测试环境中模拟依赖项 通常我在ABAPOO中使用这种模式,但不知道在Java中实现同样功能的最佳方法 以下是我在ABAPOO中所做的:我只针对接口实现,并确保能够从外部注入接口。实例化发生在构造函数中。或者,如果一个方法需要实例化某些东西,我会添加一个可选参数来注入依赖项 以下是一个例子:在Java中编写无可选参数的可测试代码的正确方法与ABAPOO中的注入,java,design-patterns,dependency-injection,abap,Java,Design Patterns,Dependency Injection,Abap,如果我想用Java编写可测试代码,并决定使用依赖项注入模式,以便能够在测试环境中模拟依赖项 通常我在ABAPOO中使用这种模式,但不知道在Java中实现同样功能的最佳方法 以下是我在ABAPOO中所做的:我只针对接口实现,并确保能够从外部注入接口。实例化发生在构造函数中。或者,如果一个方法需要实例化某些东西,我会添加一个可选参数来注入依赖项 以下是一个例子: CLASS cl_foo DEFINITION. PRIVATE SECTION. DATA: gr_dependency T
CLASS cl_foo DEFINITION.
PRIVATE SECTION.
DATA: gr_dependency TYPE REF to if_dependency. "if_dependency is an interface
PUBLIC SECTION.
METHODS: constructor IMPORTING iv_bar TYPE string, "this String makes it complicated in the Java world
ir_dependency TYPE REF TO if_dependency OPTIONAL.
"CLASS-METHODS: create_instance....
ENDCLASS.
CLASS cl_foo IMPLEMENTATION.
METHOD constructor.
IF ir_dependency IS BOUND.
gr_dependency = ir_dependency.
ELSE.
CREATE OBJECT gr_dependency TYPE cl_dependency_implementation EXPORTING iv_bar.
ENDIF.
ENDMETHOD.
ENDCLASS.
但是我如何在Java中实现同样的功能呢?没有可选参数。假设我做了这样的事情:
public class Foo {
private Dependency dependency;
public Foo(String bar, Dependency dependency) {
if(dependency == null) {
this.dependency = new DependencyImplementation(bar);
}
}
//public static Foo createInstance....
}
这几乎是相同的行为(除了“is BOUND”不同于“==null”)。但是,这并没有明确说明,您不必为接口依赖关系提供实现。另外,如果我需要引用Foo中的其他类,我必须重写实例化Foo的所有位置。大多数时候,当我编写Java代码时,我在外部设置依赖项,如果它为null,则不给类一个默认值。相反,如果它为null,我抛出一个IllegalArgumentException来强制设置该值。一般来说,我会做如下事情:
public class Foo {
private final Dependency dependency;
public Foo(Dependency dependency) {
if(dependency == null) {
throw new IllegalArgumentException("dependency must be set message.");
}
this.dependency = dependency;
}
// the rest of the code here.
}
当变量设置为final时,它将强制在构造函数中设置值,并且通过抛出异常,如果开发人员试图传递null,您将帮助程序员快速避免错过此要求,而不是稍后出现null指针异常。如果您在应用程序上下文XML文件中使用类似spring的东西来执行依赖项注入,那么这也将帮助您跟踪XML文件中的拼写错误或其他问题,因为如果您未能提供参数,它将立即失败 但是对于非常复杂的依赖关系呢?我的意思是,你不能轻易地在外部实例化每个依赖项。到目前为止,我很少遇到这样的情况:我会被迫在一个类内部实例化一个默认依赖项,我可以在某个中央DI类中实例化,或者将其放入适当的应用程序上下文中。或者,您可以使用一个不带参数的单独构造函数来实现默认依赖项,这样开发人员就可以知道已经提供了默认依赖项。(JavaDocs可以帮助确保开发人员理解您的意图。)