- 浏览: 105027 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
习惯在马桶上思考:
续在哪里啊
Spring 3.0 OXM - Spring 3.0 框架新特性 -
卖火柴的老特工:
学习了
为什么要自定义异常 -
xiarilian12:
受教了!呵呵~~~
REST是什么[精品] -
tidelgl:
不知道3.0对泛型的扫描注入支持完善了没有,现在用2.5有点抓 ...
详解 Spring 3.0 基于 Annotation 的依赖注入实现
Before you read this text, it is a good idea to have read the text "Fail Safe Exception Handling".
Correct exception handling code can be tedious to write. Try-catch blocks also clutter the code and makes it harder to read. Look at the example below:
Input input = null; IOException processException = null; try{ input = new FileInputStream(fileName); //...process input stream... } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; }
In this example no exceptions are lost. If an exception is thrown from within the try block, and another exception is thrown from the input.close() call in the finally block, both exceptions are preserved in the MyException instance, and propagated up the call stack.
That is how much code it takes to handle the processing of an input stream without any exceptions being lost. In fact it only even catches IOExceptions. RuntimeExceptions thrown from the try-block are not preserved, if the input.close() call also throws an exception. Isn't it ugly? Isn't it hard to read what is actually going on? Would you remember to write all that code everytime you process an input stream?
Luckily there is a simple design pattern, the Template Method, that can help you get the exception handling right everytime, without ever seeing or writing it in your code. Well, maybe you will have to write it once, but that's it.
What you will do is to put all the exception handling code inside a template. The template is just a normal class. Here is a template for the above input stream exception handling:
public abstract class InputStreamProcessingTemplate { public void process(String fileName){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); doProcess(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } //override this method in a subclass, to process the stream. public abstract void doProcess(InputStream input) throws IOException; }
All the exception handling is encapulated inside the InputStreamProcessingTemplate class. Notice how the process() method calls the doProcess() method inside the try-catch block. You will use the template by subclassing it, and overriding the doProcess() method. To do this, you could write:
new InputStreamProcessingTemplate(){ public void doProcess(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } }.process("someFile.txt");
This example creates an anonymous subclass of the InputStreamProcessingTemplate class, instantiates an instance of the subclass, and calls its process() method.
This is a lot simpler to write, and easier to read. Only the domain logic is visible in the code. The compiler will check that you have extended the InputStreamProcessingTemplate correctly. You will typically also get more help from your IDE's code completion when writing it, because the IDE will recognize both the doProcess() and process() methods.
You can now reuse the InputStreamProcessingTemplate in any place in your code where you need to process a file input stream. You can easily modify the template to work for all input streams and not just files.
Using Interfaces Instead of Subclassing
Instead of subclassing the InputStreamProcessingTempate you could rewrite it to take an instance of an InputStreamProcessor interface. Here is how it could look:
public interface InputStreamProcessor { public void process(InputStream input) throws IOException; } public class InputStreamProcessingTemplate { public void process(String fileName, InputStreamProcessor processor){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); processor.process(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName; } else { throw new MyException(e, "Error closing InputStream for file " + fileName); } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } }
Notice the extra parameter in the template's process() method. This is the InputStreamProcessor, which is called from inside the try block (processor.process(input)). Using this template would look like this:
new InputStreamProcessingTemplate() .process("someFile.txt", new InputStreamProcessor(){ public void process(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } });
It doesn't look much different from the previous usage, except the call to the InputStreamProcessingTemplate.process() method is now closer to the top of the code. This may be easier to read.
Static Template Methods
It is also possible to implement the template method as a static method. This way you don't need to instantiate the template as an object every time you call it. Here is how the InputStreamProcessingTemplate would look as a static method:
public class InputStreamProcessingTemplate { public static void process(String fileName, InputStreamProcessor processor){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); processor.process(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } }
The process(...) method is simply made static. Here is how it looks to call the method:
InputStreamProcessingTemplate.process("someFile.txt", new InputStreamProcessor(){ public void process(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } });
Notice how the call to the template's process() method is now a static method call.
Summary
Exception handling templates are a simple yet powerful mechanism that can increase the quality and readability of your code. It also increases your productivity, since you have much less code to write, and less to worry about. Exceptions are handled by the templates. And, if you need to improve the exception handling later in the development process, you only have a single spot to change it in: The exception handling template.
The Template Method design pattern can be used for other purposes than exception handling. The iteration of the input stream could also have been put into a template. The iteration of a ResultSet in JDBC could be put into a template. The correct execution of a transaction in JDBC could be put into a template. The possibilities are endless.
Context reuse and templates are also discussed in the article Code Reuse: Context and Action Reuse.
发表评论
-
java的几种对象(PO,VO,DAO,BO,POJO,DTO)解释
2011-02-23 14:58 1207... -
为什么要自定义异常
2010-12-12 15:27 1981为什么要自定义异常? 自定义异常是为了设置异常链的起点。 ... -
REST与SOAP区别
2010-12-12 14:51 1267如果你需要使用WSDL来发布你的服务,或者你需要一些安全功能如 ... -
有包类调用无包类(java反射机制运用)
2010-12-03 17:58 1194try { //Class[] stri ... -
【转载】反面模式(Anti-pattern)
2010-12-03 11:02 1004[目录] [1. 已知的反面模式] [1.1 组织结构的反 ... -
软件公司的岗位职责
2010-10-29 09:47 1010软件公司的岗位职责 ... -
中文参数编码后传递依然乱码解决方法(java.net.URLEncoder.encode)
2010-10-27 16:35 2729使用java.net.URLEncoder.encode()可 ... -
log4j日志处理
2010-10-26 11:07 10531.log4j与Jakarta Commons Logging ... -
Log4j每天或每个月产生一个日志文件
2010-08-16 10:34 2058Log4j每天或每个月产生一个日志文件 我们开发的B/ ... -
REST是什么[精品]
2010-07-07 09:41 1244概述 REST是英文Repr ... -
对REST中无状态(stateless)的理解
2010-07-06 17:52 3390无状态指的是任意一个Web请求必须完全与其他请求隔离,当请求端 ... -
REST及RESTful的实现
2010-07-06 16:08 786REST及RESTful的实现 ... -
为什么Java 中要使用 Checked Exceptions?
2010-06-24 16:14 729设计中常被忽略的一块:http://www.iteye.com ... -
通过request.getContextPath获取绝对路径
2010-06-07 11:45 4033<%=request.getContextPath()% ...
相关推荐
java编码规范 codeTemplates
codeTemplates.xml,因为项目的需要,发现需要自己编写一个模板,从网上下载的感觉不太适合自己,于是就自己总结拼凑了一个,当然,你也可以下载之后根据你的需求再处理一下,有需要的拿走,不谢
eclipse formatter和codetemplates java代码编写规范 eclipse formatter和codetemplates java代码编写规范
Java模板 Java代码模板,用于比赛编程
它是一个小引擎,可以处理任何模板工作,纯文本,标记,降价,无论何时何地。 块小巧,快速,易学但功能强大。 块模板提供了丰富的功能集:标记内过滤器,标记内默认值(包括循环和分支),为每个模板文件定义多...
java 注释模版 codetemplates.xml
java开发规范化模板codetemplates,开发中类、方法、变量等的规范化、格式化处理。
代码风格模板 codetemplates.xml
Zabbix 模板 H3C交换机通用模板zbx_export_templates,Zabbix 模板 H3C交换机通用模板:主要监控cup和内存的利用率及各端口的状态,带触发器和图形。
MyEclipse注释模板下载,codetemplates模板
java代码模板,codetemplates.xml,codeFormatter.xml
自己定义的注释模板,还算比较好用。用法是直接下载文件,在eclipse或myeclipse里面导入(preferences -- code templates -- comments -- import),使用的快捷键是 alt+shift+j,注释就自动加好了。
java开发注释模板文件 CodeTemplates.xml
010 Editor Templates 刚刚下载的,全新的010模板文件, 打包下载了
ASP.NET MVC beta 模板(Templates) 中文修正补丁 完整版 2008年10月15日 发布的 ASP.NET MVC beta ,安装后,在VS2008中模板(Template)没有正确显示。 此补丁解决此问题。方便一起学习ASP.NET MVC 的朋友~ 需要...
eclipse里的java 注释模板。
针对Java代码快捷模板;IDEA模板(Live Templates), 配置路径:<your_user_home_directory>\.IntelliJ IDEA<version_number>\config\templates
zabbix监控系统 Cisco_2960_templates思科交换机模板
公司用的eclipse注释模板codetemplates,经过多次升级最终版本
eclipse 标准 codetemplates.xml 代码模板,标准、简洁、好用