我有枚举说ErrorCodes
public enum ErrorCodes {
INVALID_LOGIN(100),
INVALID_PASSWORD(101),
SESSION_EXPIRED(102) ...;
private int errorCode;
private ErrorCodes(int error){
this.errorCode = error;
} //setter and getter and other codes
}
现在我用这个错误代码检查我的异常错误代码。如果这样做,我不想写,如果这样做的话。我如何解决这个问题(如果是块,写10+)
那种情况有没有设计模式?
由于
答案 0 :(得分:7)
使用if语句或开关执行此操作,或者只是以某种方式将有问题的逻辑实现到ErrorCode中。
以OO方式,这一切都取决于您希望应用程序或系统对错误代码做出反应的方式。让我们说你只想输出一些对话框:
public doSomethingWithError() {
ErrorCodes e = getError();
// the source of error, or originator, returns the enum
switch(e) {
case ErrorCodes.INVALID_LOGIN:
prompt('Invalid Login');
case ErrorCodes.INVALID_PASSWORD:
prompt('Invalid password');
// and so on
}
}
我们可以改为创建一个ErrorHandler类来代替它:
// We'll implement this using OO instead
public doSomethingWithError() {
ErrorHandler e = getError();
// the originator now returns an ErrorHandler object instead
e.handleMessage();
}
// We will need the following abstract class:
public abstract class ErrorHandler {
// Lets say we have a prompter class that prompts the message
private Prompter prompter = new Prompter();
public final void handleMessage() {
String message = this.getMessage();
prompter.prompt(message);
}
// This needs to be implemented in subclasses because
// handleMessage() method is using it.
public abstract String getMessage();
}
// And you'll have the following implementations, e.g.
// for invalid logins:
public final class InvalidLoginHandler() {
public final String getMessage() {
return "Invalid login";
}
}
// E.g. for invalid password:
public final class InvalidPasswordHandler() {
public final String getMessage() {
return "Invalid password";
}
}
前一种解决方案易于实现,但随着代码变大而变得难以维护。后一种解决方案更复杂,(Template Method pattern后面的Open-Closed Principle),但是当您需要时(例如恢复资源或其他任何内容),您可以在ErrorHandler
中添加更多方法。您也可以使用Strategy pattern实现此目的。
您不会完全使用条件语句,但在后者中,条件被推送到发生错误的代码部分。这样,您就不会在发起者和错误处理代码上对条件语句进行双重维护。
编辑:
如果您想这样做,请参阅this answer by Michael Borgwardt和this answer by oksayt了解如何在Java Enums上实现方法。
答案 1 :(得分:4)
Java枚举功能非常强大,允许按实例方法实现:
public enum ErrorCode {
INVALID_LOGIN {
public void handleError() {
// do something
}
},
INVALID_PASSWORD {
public void handleError() {
// do something else
}
},
SESSION_EXPIRED {
public void handleError() {
// do something else again
}
};
public abstract void handleError();
}
然后您只需拨打errorCode.handleError();
即可。但是,ErrorCode枚举是否真的适合该逻辑是值得怀疑的。
答案 2 :(得分:3)
正如Spoike所指出的,使用多态来选择正确的错误处理方法是一种选择。通过定义类层次结构,这种方法基本上将10+ if块推迟到JVM的虚方法查找。
但在进入一个完整的类层次结构之前,还要考虑使用enum
方法。如果您计划在每种情况下执行的操作非常相似,则此选项很有效。
例如,如果您想为每个ErrorCode
返回不同的错误消息,您只需执行以下操作:
// Note singular name for enum
public enum ErrorCode {
INVALID_LOGIN(100, "Your login is invalid"),
INVALID_PASSWORD(101, "Your password is invalid"),
SESSION_EXPIRED(102, "Your session has expired");
private final int code;
private final String
private ErrorCode(int code, String message){
this.code = code;
this.message = message;
}
public String getMessage() {
return message;
}
}
然后您的错误处理代码变为:
ErrorCode errorCode = getErrorCode();
prompt(errorCode.getMessage());
这种方法的一个缺点是,如果要添加其他案例,则需要修改枚举本身,而使用类层次结构,您可以添加新案例而无需修改现有代码。
答案 3 :(得分:2)
我相信你能做的最好的就是实施战略模式。这样,您在添加新枚举时不必更改现有类,但仍可以扩展它们。 (开闭原理)。
搜索策略模式和开放封闭原则。
答案 4 :(得分:0)
您可以针对枚举类型
创建错误代码(整数)的映射修改强>
在此解决方案中,一旦准备好地图,您就可以在地图中查找错误代码,因此不需要if..else查找。
E.g。
Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>();
for (ErrorCodes error : ErrorCodes.values()) {
errorMap.put(error.getCode(), error);
}
现在,当您想检查来自您的应用程序的错误代码时,您需要做的就是,
ErrorCodes error = errorMap.get(erro_code_from_application);
因此不需要所有if..else。
您只需要以添加错误代码不需要更改其他代码的方式设置地图。地图的准备是一次性活动,可以在应用程序初始化期间链接到数据库,属性文件等
答案 5 :(得分:0)
在我看来,ErrorCodes作为枚举和switch语句分派错误处理没有任何问题。枚举和开关很好地配合在一起。
但是,也许您会发现以下内容(过度设计),请参阅an Example 或"Double dispatching" on Wikipedia。 假设要求:
代码:
//Inteface for type-safe error handler
interface ErrorHandler {
void handleInvalidLoginError(InvalidLoginError error);
void handleInvalidPasswordError(InvalidLoginError error);
//One method must be added for each kind error. No chance to "forget" one.
}
//The error hierachy
public class AbstractError(Exception) {
private int code;
abstract public void handle(ErrorHandler);
}
public class InvalidLoginError(AbstractError) {
private String additionalStuff;
public void handle(ErrorHandler handler) {
handler.handleInvalidLoginError(this);
}
public String getAdditionalStuff();
}
public class InvalidPasswordError(AbstractError) {
private int code;
public void handle(ErrorHandler handler) {
handler.handleInvalidPasswordError(this);
}
}
//Test class
public class Test {
public void test() {
//Create an error handler instance.
ErrorHandler handler = new LoggingErrorHandler();
try {
doSomething();//throws AbstractError
}
catch (AbstractError e) {
e.handle(handler);
}
}
}