首先,我使用Scala,但任何Java方法都可以。 (我将使用Java代码作为示例,以便更容易理解。)
说我有一个Connection
界面及其实施RealConnection
和FakeConnection
。
我想在我的应用程序中包含两个条目:一个发布条目和一个测试条目。我希望像平常一样编写我的应用程序代码,然后开始使用发布版本所有类的测试,但有一个例外,它使用FakeConnection
代替RealConnection
。
我的应用程序通过Connection.get()
访问连接。
我不想要的是这样的:
public static Connection get() {
if ( isReleaseVersion )
return new RealConnection();
return new FakeConnection();
}
我希望我的应用程序代码不会被这种代码污染。
有一个Config
对象是可能的,如:
public static Connection get() {
return Config.getConnectionFactory().get();
}
这里的问题是我每次要测试时都需要更改Config
课程。如果没有其他方法,我可能会使用这种方法。
我不想使用的是定制者。我想处理final
变量或函数!不是这样的:
public class TestEntry {
public static void main(String... args) }
Config.connectionFactory = new FakeConnectionFactory();
Config.databaseConnection = new FakeDatabaseConnection(); // Singleton, no factory needed.
MyApplication.start(args); // the ReleaseEntry is somewhere else!
}
}
我不想使用的是Guice
。每次我想做测试时,我都必须重新定义我的模块。另外,我不想在Scala中使用它。
Reflection
是可能的,但错误只会出现在运行时,所以它不是很好。
有没有其他选择来实现我的目标?
我是否必须采用Config
方式?
问候。
答案 0 :(得分:1)
你的问题包含矛盾:
您希望全球可用
我的应用程序通过
访问Connection
Connection.get()
未使用变量
存储我不想使用的是定制者。我想处理最终变量或函数!
但是你想在运行时提供这个实现。
其他人提到“依赖注入”是一种“控制倒置”的形式,你问题中的要求告诉我这就是你想要的。
如果您不想使用变量,则必须使用连接将正确的实例传递给组件。使用Scala,您可以选择将其传递给implicitly
而不是explicitly
。
class MyComponent(name:String)(implicit c:Configuration)
implicit val configuration = new TestConfiguration
//note that the configuration is passed in implicitly
val m = new MyComponent("foo")
此要求也使其他选项变得棘手:
反射是可能的,但错误只会出现在运行时
如果您不想更改任何要求,您可能(理论上)可以使用Scala宏等方法来执行此操作。如果这就是你想要的,我建议你创建一个新问题。