在检查默认响应时避免代码重复



我有一个Java程序,它调用外部API(下面代码中的RealApi(,有时我想避免调用这个API,而是返回预先构建的响应(由FakeApi生成(。

因此,我最终在我的大多数方法中复制了这种结构:

public Type1 m1(String s) {
try {
Type1 r = FakeApi.m1(s);
if (r != null) {
return r;
}
} catch (Exception e) {
// log error
}
return RealApi.m1(s);
}

有哪些选项可以避免在任何地方复制这个try/catch块?重要的是,如果FakeApi抛出异常或返回null,则必须调用RealApi

一个选项是将错误检查行为封装到自己的方法中:

public <T> T fakeOrReal(Supplier<T> fake, Supplier<T> real) {
try {
T r = fake.get();
if (r != null) {
return r;
}
}
catch (Exception e) {
// log error
}
return real.get();
}

然后你可以用来称呼它

public Type1 m1(String s) {
return fakeOrReal(() -> FakeApi.m1(s), () -> RealApi.m1(s));
}

这并不像Thomas Preißler的答案那么简单,但它将帮助您完全不重复任何方法。因此,如果你扩展接口,你只需要修改具体的类,而不需要修改描述你想要的实际行为的链接器。

创建一个包含RealApi:所有方法的接口

interface Api {
Type1 m1(String s);
}

然后是一个进行实际调用的类:

class ConcreteApi implements Api {
public Type1 m1(String s) {
return RealApi.m1(s);
}
}

然后创建你的FakePi:

class TotallyFakeApi implements Api {
public Type1 m1(String s) {
return FakeApi.m1(s);
}
}

现在,避免重复自己的棘手部分:

private static Object callImplementation(Api api, Method method, Object[] methodArgs) throws Exception {
Method actualMethod = api.getClass().getMethod(actualMethod.getName(), actualMethod.getParameterTypes());
return actualMethod.invoke(api, methodArgs);
}
Api fakeOrReal(Api fakeApi, Api realApi) {
return (Api) Proxy.newProxyInstance(
FakeApi.class.getClassLoader(),
new Class[]{Api.class},
(proxy, method, methodArgs) -> {
try {
Object r = callImplementation(fakeApi, method, methodArgs);
if (r != null) {
return r;
}
} catch (Exception e) {
// logError(e);
}
return callImplementation(realApi, method, methodArgs);
}
);

}

实际实现如下:

Api apiToUse = fakeOrReal(new TotallyFakeApi(), new ConcreteApi());

相关内容

最新更新