众所周知,防御性编程是一个编程的最佳实践。良好的防御性编程,可以增强程序的健壮性,但是没有银弹,最佳实践也有一个适用场景的问题。
试看如下代码:
这段代码是一段很通用的异常处理代码,接口的定义很简洁,aboutToHandle方法来确定是否由该异常处理器来处理该异常,handle方法是实际的异常处理方法。DefaultExceptionHandler这个异常处理器实际上起着一个分发异常的作用,是这个异常处理机制的核心。
初看这段代码,会认为这段代码和大多数的异常处理机制大同小异,没有什么问题。细致的检查之后,这段代码还是有它的缺点的。
1 NullPointerExceptionHandler的aboutToHandle方法体不够简洁。
2 NullPointerExceptionHandler的handle方法中用了防御性编程,在该特定场景中防御性代码是冗余的。
一般而言,异常处理系统是作为基础子系统存在的,不应该被外界的代码随意调用。因此,异常处理的具体实现应该信任作为该系统中的核心类(该处为DefaultExceptionHandler)的功能。即分发给一个处理器的异常,一定是可以通过该处理器aboutToHandle方法测试通过的,如果该条件不满足,aboutToHandle方法的存在本身也就没有意义了。该方法本身就是对异常处理器可以处理哪些异常的一个抽象。
基于以上理解,代码修改如下:
试看如下代码:
/**
* 异常处理接口。
* */
public interface ExceptionHandler {
/**
* 是否处理该异常。
* */
public boolean aboutToHandle(Exception ex);
/**
* 处理异常。
* */
public void handle(Exception ex);
}
/**
* 默认异常处理器。
* */
public class DefaultExceptionHandler implements ExceptionHandler {
// get exceptionHandlerList from config file or somewhere.
private List<ExceptionHandler> exceptionHandlerList;
@Override
public boolean aboutToHandle(Exception ex) {
return true;
}
@Override
public void handle(Exception ex) {
for (ExceptionHandler exceptionHandler : exceptionHandlerList) {
if (exceptionHandler.aboutToHandle(ex)) {
exceptionHandler.handle(ex);
return;
}
}
}
}
/**
* 空指针异常处理器。
* */
public class NullPointerExceptionHandler_0 implements ExceptionHandler {
@Override
public boolean aboutToHandle(Exception ex) {
if (ex instanceof NullPointerException) {
return true;
}
return false;
}
@Override
public void handle(Exception ex) {
NullPointerException exception = null;
if (ex instanceof NullPointerException) {
exception = (NullPointerException) ex;
}
if (exception == null) {
return;
}
// 其他处理
}
}
这段代码是一段很通用的异常处理代码,接口的定义很简洁,aboutToHandle方法来确定是否由该异常处理器来处理该异常,handle方法是实际的异常处理方法。DefaultExceptionHandler这个异常处理器实际上起着一个分发异常的作用,是这个异常处理机制的核心。
初看这段代码,会认为这段代码和大多数的异常处理机制大同小异,没有什么问题。细致的检查之后,这段代码还是有它的缺点的。
1 NullPointerExceptionHandler的aboutToHandle方法体不够简洁。
2 NullPointerExceptionHandler的handle方法中用了防御性编程,在该特定场景中防御性代码是冗余的。
一般而言,异常处理系统是作为基础子系统存在的,不应该被外界的代码随意调用。因此,异常处理的具体实现应该信任作为该系统中的核心类(该处为DefaultExceptionHandler)的功能。即分发给一个处理器的异常,一定是可以通过该处理器aboutToHandle方法测试通过的,如果该条件不满足,aboutToHandle方法的存在本身也就没有意义了。该方法本身就是对异常处理器可以处理哪些异常的一个抽象。
基于以上理解,代码修改如下:
/**
* 重构后的空指针异常处理器。
* */
public class NullPointerExceptionHandler_1 implements ExceptionHandler {
@Override
public boolean aboutToHandle(Exception ex) {
return (ex instanceof NullPointerException);
}
@Override
public void handle(Exception ex) {
NullPointerException exception = (NullPointerException) ex;
// 其他处理
}
}