“if”声明与OO设计

我有枚举说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 } 

现在我用这个错误代码检查我的exception错误代码。 如果这样做,我不想写,如果这样做的话。 我怎么能解决这个问题(如果块写10+)

这种情况有什么设计模式吗?

谢谢

正如Spoike所指出的,使用多态来选择正确的error handling方法是一种选择。 通过定义类层次结构,此方法基本上将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; } } 

然后您的error handling代码变为:

 ErrorCode errorCode = getErrorCode(); prompt(errorCode.getMessage()); 

这种方法的一个缺点是,如果要添加其他案例,则需要修改枚举本身,而使用类层次结构,您可以添加新案例而无需修改现有代码。

您可以使用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, eg // for invalid logins: public final class InvalidLoginHandler() { public final String getMessage() { return "Invalid login"; } } // Eg for invalid password: public final class InvalidPasswordHandler() { public final String getMessage() { return "Invalid password"; } } 

前一种解决方案易于实现,但随着代码变大而变得难以维护。 后一种解决方案更复杂,(也就是开放 – 封闭原则之后的模板方法模式 ),但是您可以在需要时将更多方法添加到ErrorHandler (例如恢复资源或其他)。 您也可以使用策略模式实现此function。

您不会完全使用条件语句,但在后者中,条件被推送到发生错误的代码部分。 这样,您就不会在发起者和error handling代码上对条件语句进行双重维护。

编辑:

请参阅Michael Borgwardt的 回答以及oksayt的回答,了解如何在Java Enums上实现方法。

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枚举是否真的适合该逻辑是值得怀疑的。

我相信你能做的最好的就是实施战略模式。 这样,您在添加新枚举时不必更改现有类,但仍可以扩展它们。 (开闭原则)。

寻找战略模式和开放封闭原则。

您可以针对枚举类型创建错误代码(Integer)的映射

编辑

在此解决方案中,一旦准备好地图,您就可以在地图中查找错误代码,因此不需要if..else查找。

例如

 Map errorMap = new HashMap(); for (ErrorCodes error : ErrorCodes.values()) { errorMap.put(error.getCode(), error); } 

现在,当您想要检查来自您的应用程序的错误代码时,您需要做的就是,

 ErrorCodes error = errorMap.get(erro_code_from_application); 

从而消除了对所有if..else的需求。

您只需要以添加错误代码不需要更改其他代码的方式设置地图。 地图的准备是一次性活动,可以在应用程序初始化期间链接到数据库,属性文件等

在我看来,ErrorCodes作为枚举和switch语句分派error handling没有任何问题。 枚举和开关非常合适。

但是,也许您会发现以下内容(过度设计的类型),请参阅维基百科上 的示例或“双重调度” 。 假设要求:

  • error handling应该封装在自己的类中
  • error handling应该是可替换的
  • 类型安全:每当添加错误时,您都被迫在每个error handling程序实现中添加error handling。 在一个(可能很多)切换器状态中“忘记”错误是不可能的。

代码:

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