我在java中开发了一个包含大约30个操作的Web服务。除2-3行外,每个操作都具有完全相同的代码。以下是代码草图
public Response operation1(String arg1, String arg2)
{
initialze(); // this line will be different for each operation with different arguments
authorizeSession();
Response res;
if (authorized)
{
try
{
Object result = callMethod1(arg1, arg2); // This line is different for each operation
res = Response.ok(result).build();
}
catch( MultipleExceptions ex)
{
res = handleExceptions();
}
finally
{
logInDatabase();
}
}
return res;
}
我应该遵循什么方法,以便我不必在每个操作中编写相同的代码?
答案 0 :(得分:8)
这看起来像template method pattern的好候选人。定义一个包含main方法(final)的抽象类,它将特定部分委托给受保护的抽象方法。
在Web服务的每个方法中,实例化此抽象类的子类,该子类仅覆盖两个特定的抽象方法,并调用此子类实例的main方法。
public abstract class Operation {
public final Response answer(String arg1, String arg2) {
authorizeSession();
Response res;
if (authorized) {
try {
Object result = executeSpecificPart(arg1, arg2);
res = Response.ok(result).build();
}
catch (MultipleExceptions ex) {
res = handleExceptions();
}
finally {
logInDatabase();
}
}
return res;
}
protected abstract Object executeSpecificPart(String arg1, String arg2);
}
...
public Response operation1(final String arg1, final String arg2) {
initialize();
Operation op1 = new Operation() {
protected Object executeSpecificPart(String arg1, String arg2) {
...
}
};
return op1.answer();
}
答案 1 :(得分:4)
每个方法都创建自己的Callable
实例,并将其传递给一个通用run()
方法:
public Response operation1(String arg1, String arg2)
{
initialze(); // this line will be different for each operation with different arguments
return run(new Callable<Object> {
public Object call() {
return callMethod1(arg1, arg2); // This line is different for each operation
}
});
}
private Response run(Callable<Object> method) {
authorizeSession();
if (authorized)
{
try
{
Object result = method.call();
return Response.ok(result).build();
}
catch( MultipleExceptions ex)
{
return handleExceptions();
}
finally
{
logInDatabase();
}
}
return null;
}
如果Java有lambdas,那么读写会更容易。
面向方面的编程不是最好的工具,因为你必须拦截里面方法。当你需要在方法之前或之后(或者当它抛出某些东西时)调用某些东西时,AOP最适合。这同样适用于反思。
然而,AOP将显着改善错误处理。然后您的代码可以简化为:
public Response operation1(String arg1, String arg2)
{
initialze(); // this line will be different for each operation with different arguments
authorizeSession();
if (authorized)
{
Object result = callMethod1(arg1, arg2); // This line is different for each operation
return Response.ok(result).build();
}
return null;
}
并抓住MultipleExceptions
和finally block can be placed in
AfterThrowing and
之后的建议。
答案 2 :(得分:0)
在这种情况下,您只需使用私有方法提取代码即可。
1。)反思将使它变得更慢,更难以理解和维护。
2。)当一个问题横切另一个问题时,应该使用AO技术。这不是真的,因为initialize
和callMethod1
是整个算法的一部分,不能单独使用。
3。)开关语句是正确的思维方式,但却是“多态性”的标志。
你可以这样做:
private static interface CallMethodHelper {
Object callMethod() throws MultipleExceptions;
}
public Response operation1(final String arg1, final String arg2) {
initialze();
return operationHelper(new CallMethodHelper() {
@Override
public Object callMethod() throws MultipleExceptions {
return callMethod1(arg1, arg2);
}
});
}
private Response operationHelper(CallMethodHelper helper) {
authorizeSession();
Response res = null;
if (authorized) {
try {
Object result = helper.callMethod();
res = Response.ok(result).build();
} catch (MultipleExceptions ex) {
res = handleExceptions();
} finally {
logInDatabase();
}
}
return res;
}
请注意,您必须将参数设为final,并且您当然可以使用泛型来更改结果和异常类型。