如何将包含 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();
}

只有看起来非常相似的代码块,我想在某个地方打破这个逻辑,但处理不同的成功/失败场景让我很难。

你的代码中已经有"一半"的答案:

Mailman mailman = requestMailForPerson(person);

与。

Mailman mailman = rerouteLetterForPerson(letter, person);

这里的关键点是:这些不应该是"相同"的 Mailman 类对象。Mailman 可能是一个接口,您的方法返回不同的实现!

然后你只需调用一个方法,如

mailman.doYourJob();

你会得到正确的结果;这取决于底层的实现代码!

您完全正确,因为这种内部状态代码的开关具有非常难闻的气味。它违反了"告诉不问"原则。这是你真正想要避免的部分:你不想将这种状态外部化,并让其他">外部"代码基于此做出决策!

你可以在函数中添加一个标志,说明是否检查距离:

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);

如果要减少代码重复并使代码更具可读性,回调函数可能是一个可行的选择。只需"告诉"方法在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;
            }
        });

最新更新