只是为了使@Robin 对策略模式的建议更加具体:(请注意,您原始问题的公共 API 保持不变。)
public class MyLegacyClass {
private static Strategy strategy = new JNDIStrategy();
public static SomeLegacyClass doSomeLegacyStuff(SomeOtherLegacyClass legacyObj) {
// legacy logic
SomeLegacyClass result = strategy.doSomeStuff(legacyObj);
// more legacy logic
return result;
}
static void setStrategy(Strategy strategy){
MyLegacyClass.strategy = strategy;
}
}
interface Strategy{
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj);
}
class JNDIStrategy implements Strategy {
private static final String jndiName = "java:comp/env/jdbc/LegacyDataSource";
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
// do stuff using jndiName
}
}
...和 JUnit 测试。我不太喜欢进行这种设置/拆卸维护,但这是拥有基于静态方法(或单例)的 API 的不幸副作用。我喜欢这个测试的地方是它不使用 JNDI - 这很好,因为 (a) 它会运行得很快,并且 (b) 单元测试应该只测试 doSomeLegacyStuff() 方法中的业务逻辑,而不是测试实际数据源。(顺便说一句,这假设测试类与 MyLegacyClass 在同一个包中。)
public class MyLegacyClassTest extends TestCase {
private MockStrategy mockStrategy = new MockStrategy();
protected void setUp() throws Exception {
MyLegacyClass.setStrategy(mockStrategy);
}
protected void tearDown() throws Exception {
// TODO, reset original strategy on MyLegacyClass...
}
public void testDoSomeLegacyStuff() {
MyLegacyClass.doSomeLegacyStuff(..);
assertTrue(..);
}
static class MockStrategy implements Strategy{
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
// mock behavior however you want, record state however
// you'd like for test asserts. Good frameworks like Mockito exist
// to help create mocks
}
}
}