如何处理 Java 中的多个退出点
How to handle multiple exit points in Java
有时我会遇到一个例程,该例程将测试某些条件并继续或退出,类似于以下代码:
public void execute() {
if (context.condition1()) {
LOGGER.info("Condition 1 not satisfied.");
return;
}
doSomeStuff();
if (context.condition2()) {
LOGGER.info("Condition 2 not satisfied.");
return;
}
if (context.condition3()) {
LOGGER.info("Condition 3 not satisfied.");
return;
}
doRestOfStuff();
}
假设在进入此方法之前无法测试这些条件。也许这是一个带有单一入口点的 servlet 或控制器。根据我的经验(远非广泛),这似乎是一种普遍情况。
现在,这段代码不太好闻,是吗?处理此问题的最佳策略是什么?
这是我到目前为止的想法:
public void execute() {
checkCondition1AndExecute();
}
private void checkCondition1AndExecute() {
if (context.notCondition1()) {
doSomeStuff();
checkCondition2AndExecute();
} else {
LOGGER.info("Condition 1 not satisfied.");
}
}
private void checkCondition2AndExecute() {
if (context.notCondition2()) {
checkCondition3AndExecute();
} else {
LOGGER.info("Condition 2 not satisfied.");
}
}
private void checkCondition3AndExecute() {
if (context.notCondition3()) {
doRestOfStuff();
} else {
LOGGER.info("Condition 3 not satisfied.");
}
}
它看起来不太好,但对我来说确实闻起来更好。我没有使用具有多个出口的大方法,而是使用小方法,每个方法负责一个特定条件(和出口点)。此外,它摆脱了愚蠢的 return;
行。
但是,我仍然想知道是否有一种模式或更好的策略来处理这个问题。
尝试阅读 switch 语句,它是多种语言的解决方案,特别是 java:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
我们在谈论多少个不同的退出点?
如果像您的示例中那样只有 3 个,那么您的原始代码就可以了。它很容易阅读。我会将 "only have one exit point" 视为一般指导方针,而不是硬性规定。
将其更改为 if
/ else if
块的嵌套组我发现更难阅读,尤其是在缩进之后。如果您将来必须添加更多条件检查,您还 运行 有忘记将新条件正确放置到链中的风险。
但是,如果您有很多条件并且可能需要添加更多条件(可能在 运行 时),那么您可以利用 Chain of Responsibility
模式。
最终结果看起来像这样:
public void execute() {
List<Condition> conditionChains = ....
for(Condition condition : conditionChain){
if(condition.notSatisfied(context)){
//here use condition#toString() to explain what wasn't satisfied.
//Could use another method like getDescrption() instead...
LOGGER.info(condition + " not satisfied.");
return;
}
condition.execute(context);
}
}
你会有一个接口 Condition
,它有 2 个方法来检查可满足性,然后另一个方法来执行任何相关代码。
示例实现:
class Condition1 implements Condition{
public boolean isSatisfied(Context context){
...
}
public void execute(Context context){
doSomeStuff();
}
}
class Condition2 implements Condition{
public boolean isSatisfied(Context context){
...
}
public void execute(Context context){
//do nothing
}
}
class Condition3 implements Condition{
public boolean isSatisfied(Context context){
return !context.notCondition3();
}
public void execute(Context context){
doRestOfStuff();
}
}
有时我会遇到一个例程,该例程将测试某些条件并继续或退出,类似于以下代码:
public void execute() {
if (context.condition1()) {
LOGGER.info("Condition 1 not satisfied.");
return;
}
doSomeStuff();
if (context.condition2()) {
LOGGER.info("Condition 2 not satisfied.");
return;
}
if (context.condition3()) {
LOGGER.info("Condition 3 not satisfied.");
return;
}
doRestOfStuff();
}
假设在进入此方法之前无法测试这些条件。也许这是一个带有单一入口点的 servlet 或控制器。根据我的经验(远非广泛),这似乎是一种普遍情况。
现在,这段代码不太好闻,是吗?处理此问题的最佳策略是什么?
这是我到目前为止的想法:
public void execute() {
checkCondition1AndExecute();
}
private void checkCondition1AndExecute() {
if (context.notCondition1()) {
doSomeStuff();
checkCondition2AndExecute();
} else {
LOGGER.info("Condition 1 not satisfied.");
}
}
private void checkCondition2AndExecute() {
if (context.notCondition2()) {
checkCondition3AndExecute();
} else {
LOGGER.info("Condition 2 not satisfied.");
}
}
private void checkCondition3AndExecute() {
if (context.notCondition3()) {
doRestOfStuff();
} else {
LOGGER.info("Condition 3 not satisfied.");
}
}
它看起来不太好,但对我来说确实闻起来更好。我没有使用具有多个出口的大方法,而是使用小方法,每个方法负责一个特定条件(和出口点)。此外,它摆脱了愚蠢的 return;
行。
但是,我仍然想知道是否有一种模式或更好的策略来处理这个问题。
尝试阅读 switch 语句,它是多种语言的解决方案,特别是 java:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
我们在谈论多少个不同的退出点?
如果像您的示例中那样只有 3 个,那么您的原始代码就可以了。它很容易阅读。我会将 "only have one exit point" 视为一般指导方针,而不是硬性规定。
将其更改为 if
/ else if
块的嵌套组我发现更难阅读,尤其是在缩进之后。如果您将来必须添加更多条件检查,您还 运行 有忘记将新条件正确放置到链中的风险。
但是,如果您有很多条件并且可能需要添加更多条件(可能在 运行 时),那么您可以利用 Chain of Responsibility
模式。
最终结果看起来像这样:
public void execute() {
List<Condition> conditionChains = ....
for(Condition condition : conditionChain){
if(condition.notSatisfied(context)){
//here use condition#toString() to explain what wasn't satisfied.
//Could use another method like getDescrption() instead...
LOGGER.info(condition + " not satisfied.");
return;
}
condition.execute(context);
}
}
你会有一个接口 Condition
,它有 2 个方法来检查可满足性,然后另一个方法来执行任何相关代码。
示例实现:
class Condition1 implements Condition{
public boolean isSatisfied(Context context){
...
}
public void execute(Context context){
doSomeStuff();
}
}
class Condition2 implements Condition{
public boolean isSatisfied(Context context){
...
}
public void execute(Context context){
//do nothing
}
}
class Condition3 implements Condition{
public boolean isSatisfied(Context context){
return !context.notCondition3();
}
public void execute(Context context){
doRestOfStuff();
}
}