java8Lambda的环绕执行模式
Lambda表达式在实践中极大的简化了代码,而且行为的参数化让代码更加的灵活。
在资源处理(例如处理文件或数据库)时一个常见的模式就是打开一个资源,做一些处理,然后关闭资源,这段代码会围绕着执行处理的那些重要代码,这就是环绕执行模式。
也就是说在执行的开始,需要做一些准备,然后开始自己的行为操作,而在执行完成之后,需要关闭资源,在这段代码中,初始化和关闭资源就是环绕着的一段冗余代码。
看下面的例子
分为四步来理解这个模式
- 正常的代码
- 改造1:定义函数式接口
- 改造2:定义目标操作方法
- 改造3:最终成型代码
正常代码
一段很简单的代码,就是使用缓冲字符流读取data.txt文件中的一行文字。
在这段代码中已经经过了简化,只用了一个try关键字,这里java已经为我们做了一个关闭资源的操作。
1 public static String processFile() throws IOException { 2 try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))){ 3 return br.readLine(); 4 } 5 }
使用Lambda改造代码
- 定义函数式接口
在这里定义了一个函数式接口,函数式接口就是只有一个抽象方法的接口,在接口上方加入@FunctionalInterface
注解就是标记此接口为函数式接口,只能有一个抽象方法。
在这个方法的作用就是,传给我一个BufferedReader
类型的字符流,我返回给你一个字符串。
1 @FunctionalInterface 2 public interface BufferedReaderProcessor{ 3 String process(BufferedReader b) throws IOException; 4 }
- 定义操作目标方法
这段代码和正常书写基本无异,就是在参数位置多了一个BufferedReaderProcessor
参数,也就是我们刚刚定义的那个函数式接口。
接下来就让我们用Lumbda表达式来改造一下这个方法。
1 public static String processFile(BufferedReaderProcessor p) throws IOException { 2 try(BufferedReader br = new BufferedReader(new FileReader("data.txt"))) { 3 return p.process(br); 4 } 5 }
- 最终成型使用的代码
下面这段代码中不需要你做任何的读取文件,或者创建流,或者关闭流,直接书写你需要用流尽行的操作即可,完全不需要关注前后环绕的那些冗余代码。
1 String oneLine = processFile((BufferedReader br) -> br.readLine()); 2 String twoLines = processFile((BufferedReader br) -> br.readLine() + br.readLine());
这里看起来貌似比最开始的只用一个方法就能搞定的操作要复杂了许多,其实不然,咱们多做的只是定义了一个可以传递流的函数式接口,然后在方法中传递了一个参数,而在之后我们的操作中都可以复用这段代码,如果只是用一次,没有什么感觉,甚至感觉还多写了好多代码,但是如果经常用的话,好处就能体现的很明显了。