如果我有一个类似的代码块,它在很多地方使用,但功能不同但包含return语句,我该如何重构它以使这个块成为一个函数?例如,假设我有一个对象Mailman
,其中包含有效代码(失败的成功/失败/原因),也可能包含给被调用者的包。
在一个案例中,邮递员可能会抓住他所持有的物品并将其交给被叫者:
Mailman mailman = requestMailForPerson(person);
switch(mailman.getStatus()){
case SUCCESS:
Mail mail = (Mail)mailman.getHeldItem();
return Response.ok().entity(mail).build();
case PERSON_DOESNT_EXIST:
return Response.status(Response.status.BAD_REQUEST).build();
case MAIL_SERVICE_FAILED_SOMEWHERE:
return Response.status(Response.status.INTERNAL_SERVER_ERROR).build();
}
但另一方面,他可能会重新发布一封信
Mailman mailman = rerouteLetterForPerson(letter, person);
switch(mailman.getStatus()){
case SUCCESS:
Letter letter = (Letter)mailman.getHeldItem();
if(distance(letter.address, currentLocation) > 50){
sendToNextoffice(letter);
return Response.ok.entity("in transit").build();
}else{
return Response.ok().entity(letter).build();
}
case PERSON_DOESNT_EXIST:
return Response.status(Response.status.BAD_REQUEST).build();
case MAIL_SERVICE_FAILED_SOMEWHERE:
return Response.status(Response.status.INTERNAL_SERVER_ERROR).build();
}
只有一些代码块看起来非常相似,我想在某个地方突破这种逻辑,但处理不同的成功/失败场景给我带来了困难。
答案 0 :(得分:3)
你已经有了#34;一半"您的代码中的答案:
Mailman mailman = requestMailForPerson(person);
VS。
Mailman mailman = rerouteLetterForPerson(letter, person);
这里的关键点是:那些不应该是"相同" Mailman类对象。 Mailman可以是一个接口,你的方法会返回不同的实现!
然后你只需要调用类似
的方法mailman.doYourJob();
你得到了正确的结果;取决于底层实现代码!
在内部状态代码的开关具有非常错误气味的意义上,您完全正确。它违反了Tell Don't Ask原则。这是您真正想要避免的部分:您不希望外化该状态,并拥有其他"外部"代码根据这个做出决定!
答案 1 :(得分:0)
您可以在函数中添加一个标志,指出是否检查距离:
bool checkStatus(Mailman& toCheck, bool checkDistance)
{
switch(toCheck.getStatus()){
case SUCCESS:
Letter letter = (Letter)mailman.getHeldItem();
if(checkDistance && distance(letter.address, currentLocation) > 50){
sendToNextoffice(letter);
return Response.ok.entity("in transit").build();
}else{
return Response.ok().entity(letter).build();
}
case PERSON_DOESNT_EXIST:
return Response.status(Response.status.BAD_REQUEST).build();
case MAIL_SERVICE_FAILED_SOMEWHERE:
return Response.status(Response.status.INTERNAL_SERVER_ERROR).build();
}
}
然后你有用例1:
Mailman mailman = requestMailForPerson(person);
return checkStatus(mailman, false);
用例2:
Mailman mailman = rerouteLetterForPerson(letter, person);
return checkStatus(mailman, true);
答案 2 :(得分:0)
如果您想减少代码重复并使代码更具可读性,那么回调函数可能是一个可行的选择。只是"告诉"该方法在SUCCESS
案例中做了什么。
public process(Mailman mailman, Function<Mailman, Object> onSuccess) {
switch (mailman.getStatus()) {
case SUCCESS:
return Response.ok().entity(onSuccess.apply(mailman)).build();
case PERSON_DOESNT_EXIST:
return Response.status(Response.status.BAD_REQUEST).build();
case MAIL_SERVICE_FAILED_SOMEWHERE:
return Response.status(Response.status.INTERNAL_SERVER_ERROR).build();
}
}
调用函数时,只需将回调作为匿名函数或甚至只是方法引用传递:
process(requestMailForPerson(person), Mailman::getHeldItem);
process(rerouteLetterForPerson(theLetter, person),
mailman -> {
Letter letter = (Letter) mailman.getHeldItem();
if (distance(letter.address, currentLocation) > 50){
sendToNextoffice(letter);
return "in transit";
} else {
return letter;
}
});