Java8 由Oracle在2014年发布,是继Java5之后最具革命性的版本。

Java8吸收其他语言的精髓带来了函数式编程,lambda表达式,Stream流等一系列新特性,学会了这些新特性,可以让你实现高效编码优雅编码。

烂代码登场

首先引入一个实际的例子,我们常常会写一个dao类来操作数据库,比如查询记录,插入记录等。

下面的代码中实现了查询和插入功能(引入Mybatis三方件):public class StudentDao{

/**

* 根据学生id查询记录

* @param id 学生id

* @return 返回学生对象

*/

public Student queryOne(int id){

SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

SqlSession session = null;

try {

session = sqlSessionFactory.openSession();

// 根据id查询指定的student对象

return session.selectOne("com.coderspace.mapper.student.queryOne", id);

} finally {

if (session != null) {

session.close();

}

}

}

/**

* 插入一条学生记录

* @param student 待插入对象

* @return true if success, else return false

*/

public boolean insert(Student student){

SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

SqlSession session = null;

try {

session = sqlSessionFactory.openSession();

// 向数据库插入student对象

int rows = session.insert("com.coderspace.mapper.student.insert", student);

return rows > 0;

} finally {

if (session != null) {

session.close();

}

}

}

}

睁大眼睛观察上面的代码可以发现,这两个方法有很多重复的代码。

除了下面这两行,其他的代码都是一样的,都是先获取session,然后执行核心操作,最后关闭session。// 方法1中核心代码

return session.selectOne("com.coderspace.mapper.student.queryOne", id);// 方法2中核心代码

int rows = session.insert("com.coderspace.mapper.student.insert", student);

作为一个有追求的程序员,不,应该叫代码艺术家,是不是应该考虑重构一下。

获取session和关闭session这段代码围绕着具体的核心操作代码,我们可以称这段代码为模板代码。

假如又来了一个需求,需要实现删除student方法,那么你肯定会copy上面的获取session和关闭session代码,这样做有太多重复的代码,作为一名优秀的工程师肯定不会容忍这种事情的发生。

开始重构烂代码

怎么重构呢?现在请出我们的主角登场:环绕执行模式使行为参数化。

名字是不是很高大上,啥叫行为参数化?上面例子中我们已经观察到了,除了核心操作代码其他代码都是一模一样,那我们是不是可以将核心操作代码作为入参传入模板方法中,根据不同的行为分别执行。

变量对象很容易作为参数传入,行为可以作为参数传入吗?

答案是:当然可以,可以采用lambda表达式传入。

下面开始重构之前的例子,主要可以分为三步:

(1)定义函数式接口;

(2)定义模板方法;

(3)传递lambda表达式

所有的环绕执行模式都可以套用上面这三步公式。

第一步:定义函数式接口@FunctionalInterface

public interface DbOperation{

/**

* 通用操作数据库接口

* @param session 数据库连接session

* @param mapperId 关联mapper文件id操作

* @param params 操作参数

* @return 返回值,R泛型

*/

R operate(SqlSession session, String mapperId, Object params);

}

定义了一个operate抽象方法,接收三个参数,返回泛型R。

第二步:定义模板方法

DbOperation是一个函数式接口,作为入参传入:public class CommonDao{

public R proccess(DbOperation dbOperation, String mappperId, Object params){

SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

SqlSession session = null;

try {

session = sqlSessionFactory.openSession();

// 核心操作

return dbOperation.operate(session, mappperId, params);

} finally {

if (session != null) {

session.close();

}

}

}

}

第三步:传递lambda表达式// 根据id查询学生

String mapperId = "com.coderspace.mapper.student.queryOne";

int studentNo = 123;

CommonDao commonDao = new CommonDao<>();

// 使用lambda传递具体的行为

Student studentObj = commonDao.proccess(

(session, mappperId, params) -> session.selectOne(mappperId, params),

mapperId, studentNo);

// 插入学生记录

String mapperId2 = "com.coderspace.mapper.student.insert";

Student student = new Student("coderspace", 1, 100);

CommonDao commonDao2 = new CommonDao<>();

// 使用lambda传递具体的行为

Boolean successInsert = commonDao2.proccess(

(session, mappperId, params) -> session.selectOne(mappperId, params),

mapperId2, student);

实现了上面三步,假如要实现删除方法,CommonDao里面一行代码都不用改,只用在调用方传入不同的参数即可实现。

总结

环绕执行模式在项目实战中大有用途,如果你发现几行易变的代码外面围绕着一堆固定的代码,这个时候你应该考虑使用lambda环绕执行模式了。

环绕执行模式固有套路请跟我一起大声读三遍:

第一步:定义函数式接口

第二步:定义模板方法

第三步:传递lambda表达式

java 重构函数_包会,教你用Java函数式编程重构烂代码相关推荐

  1. java退出函数_如何更新线上的 Java 服务器代码

    来源:cnblogs.com/orange911/p/10583245.html 一.前言 1.热更新代码的场景 (1)当线上服务器出现问题时,有些时候现有的手段不足以发现问题所在,可能需要追加打印日 ...

  2. java isprime函数_翁恺老师零基础java课程函数章第一题分解质因数

    分解质因数(5分) 题目内容: 每个非素数(合数)都可以写成几个素数(也可称为质数)相乘的形式,这几个素数就都叫做这个合数的质因数.比如,6可以被分解为2x3,而24可以被分解为2x2x2x3. 现在 ...

  3. wpf绑定 dictionary 给定关键字不再字典中_为什么要在 JavaScript 中学习函数式编程?...

    请忘掉你认为你知道的有关 JavaScript 的任何东西,以初学者心态来接触这份资料. 为帮助你这样做,我们打算从头开始复习 JavaScript 的基础知识, 就好像你以前从来没有看到过 Java ...

  4. Java 设计模式最佳实践:一、从面向对象到函数式编程

    原文:Design Patterns and Best Practices in Java 协议:CC BY-NC-SA 4.0 贡献者:飞龙 本文来自[ApacheCN Java 译文集],采用译后 ...

  5. python 函数式编程 库_使用Python的toolz库开始函数式编程的方法

    在这个由两部分组成的系列文章的第二部分中,我们将继续探索如何将函数式编程方法中的好想法引入到 Python中,以实现两全其美. 在上一篇文章中,我们介绍了不可变数据结构 . 这些数据结构使得我们可以编 ...

  6. java length()函数_小猿圈介绍java函数式编码结构及优势

    对于java大家都已经不陌生了吧,今天小猿圈Java讲师就分享一篇关于java函数式编码结构及优势的知识点,希望对于学习java的你有一定的帮助,想学习就需要积累. 探讨三种下一代JVM语言:Groo ...

  7. java 匿名函数_国外程序员用的火热的Vavr是什么鬼?让函数式编程更简单!

    引言 相信很多人关注 Vavr 的原因,还是因为 Hystrix 库.Hystrix 不更新了,并在 GitHub 主页上推荐了 Resilience4j,而 Vavr 作为 Resilience4j ...

  8. java arraylist 函数_使用Java-8中的函数ArrayList

    问题描述: 我希望能够使用从另一个类传入的函数的ArrayList(其中函数已在其他类中定义).如果在一个类中定义了可能具有不同输入和返回类型的函数列表,我希望能够将其中一些的ArrayList(可能 ...

  9. java peek函数_基础篇:JAVA.Stream函数,优雅的数据流操作

    写在开头:本文是转载于掘金上的一篇文章,已获得原作者授权,我会在文章最后放上原作者和原文链接. 前言 平时操作集合数据,我们一般都是for或者iterator去遍历,不是很好看.java提供了Stre ...

最新文章

  1. java环境变量设置--编写一年java,竟不会配变量了
  2. C#中dynamic的正确用法 以及 typeof(DynamicSample).GetMethod(Add);
  3. PHP之composer遇见Your requirements could not be resolved to an installable set of packages
  4. 缓冲区溢出漏洞攻击演示实验(CProxy 6.2缓冲区溢出漏洞)
  5. lcx源代码以及免杀的研究
  6. 为什么AI工程师成为当前薪资最高的技术岗位
  7. 字节流复制文件 java
  8. ActiveMq笔记3-AMQ高可用性理论
  9. 【转载】Scarbee Pre-Bass 贝司的使用教程
  10. 摆摊真的一个月能上万嘛
  11. 实习日志(1)2011-12-30
  12. MarkDown安装后不能预览问题(awesomium_sdk的下载)
  13. 英特尔边缘软件中心介绍
  14. Java彩信接口开发经验及具体开发实现
  15. mui html5 vue,VUE中使用MUI方法
  16. java如何快速标记条_【JAVA】如何利用TODO任务标签高效管理代办代码
  17. 对一名电子信息工程专业应届毕业生的建议【转自没毛菜鸟要成长的一篇博文】
  18. DIY TCP/IP TCP模块的实现9
  19. goupby()分组后的排序
  20. 关于 两个 datetime 列的差别导致了运行时溢出

热门文章

  1. 一文带你了解Java的命名规范!
  2. vue html2canvas用法,vue中html2canvas的使用(地图截图)
  3. java和其他语言相比 特点,【单选题】与其他面向对象语言相比,Java语言突出的特点是:...
  4. 对于新手来说,Python 中有哪些难以理解的概念?我似乎明白了
  5. 浅谈Session与Cookie的关系
  6. Python-第一个Python程序
  7. Python中的包以及跨目录访问变量和函数(同级目录)
  8. VTK:标签放置映射器用法实战
  9. VTK:vtkCursor3D用法实战
  10. OpenCASCADE:OCCT应用框架OCAF之功能服务