我想问一下,根据下面的布尔条件,是否有很多其他if语句的好方法?
public void borrowItem() throws IOException {
boolean ableToBorrow = isUserAbleToBorrow(cardID);
boolean isDemand = checkDemand(title, authorNumber);
boolean userExists = checkIfUserExists(cardID);
if(ableToBorrow && isDemand && userExists) {
//lots of code....
}else if(!ableToBorrow && isDemand && userExists) {
System.out.println("User limit exceeded");
}else if(!ableToBorrow && !isDemand && userExists) {
System.out.println("User limit exceeded and no book demand");
}else if(ableToBorrow && !isDemand && userExists) {
System.out.println("No book demand");
}else if(ableToBorrow && !isDemand && !userExists) {
System.out.println("No book demand and user does not exists");
}else if(ableToBorrow && isDemand && !userExists) {
System.out.println("Unrecognized user!");
}
}
这是一种好方法还是在java中有更好的想法呢?
答案 0 :(得分:2)
这是非常糟糕的风格:难以阅读和理解,当您被要求增强/改变行为时容易陷入困境。请注意,此类代码也非常难以测试 - 因为您希望确保涵盖所有流可在此类方法中采用的路径。
这类事情的典型答案是使用 polymorphism ,比如有一个定义某个接口的基类,以及每个以不同方式实现接口的特定子类。
从这个意义上讲:您的代码明显违反了Tell Don't Ask:您从某处对查询某些状态进行编码,然后对此做出决策。相反,你创建类/对象并告诉他们做正确的事情(再次:这就是多态性开始的地方)。
答案 1 :(得分:2)
我同意GhostCat wrote的内容。这太程序化了。实现多态的一种方式(在这种情况下可能是最好的方法)是decorator pattern。
定义您的界面:
public interface User {
void borrowItem(String item);
String cardId();
}
创建基本实现:
public final class SimpleUser implements User {
private final String cardId;
public SimpleUser(final String cardId) {
this.cardId = cardId;
}
@Override
public void borrowItem(final String item) {
// Borrowing logic.
}
@Override
public String cardId() {
return cardId;
}
}
然后为您需要的每个验证添加装饰器。例如。检查用户是否存在:
public final class ExistingUser implements User {
private final User origin;
public ExistingUser(final User origin) {
this.origin = origin;
}
@Override
public void borrowItem(final String item) {
if (!exists(cardId())) {
throw new IllegalStateException("Unrecognized user!");
}
origin.borrowItem(item);
}
@Override
public String cardId() {
return origin.cardId();
}
private boolean exists(String cardId) {
// Check if exists...
}
}
并将它们结合起来。这样,当您需要一个额外的验证时,您需要添加一个额外的装饰器。使用if
s时,案例数将以几何方式增长。
new ExistingUser(
new DemandAwareUser(
new SafelyBorrowingUser(
new SimpleUser(cardId)
)
)
).borrowItem(item);
答案 2 :(得分:-1)
它的方式没有错,但如果您希望您的代码更简洁,还有其他选择。如果我稍微改变你的错误信息,我可以这样写:
if(ableToBorrow && isDemand && userExists) {
//lots of code....
} else {
String errorMsg = "";
if (!ableToBorrow) errorMsg += "User limit exceeded - ";
if (!isDemand) errorMsg += "No book demand - ";
if (!userExists) errorMsg += "Unrecognized user!"
System.out.println(errorMsg);
}
还可以选择将布尔值捆绑为单个整数值。这会混淆你的代码在做什么,我个人不会使用,除非你想创建一个枚举来跟踪整数值的含义;
int status = 4*(ableToBorrow?1:0)+2*(isDemand?1:0)+(userExists?1:0);
switch(status){
case 7: //lots of code....
break;
case 3: System.out.println("User limit exceeded");
break;
//etc...
}