ITPub博客

首页 > 应用开发 > Java > 【Java8新特性】02 函数式接口和Lambda表达式实战练习:环绕执行模式使行为参数化

【Java8新特性】02 函数式接口和Lambda表达式实战练习:环绕执行模式使行为参数化

原创 Java 作者:爱笑的架构师 时间:2020-09-28 14:40:20 0 删除 编辑

博主从华中科技大学硕士毕业,曾浪迹于华为、百度大厂,是一个对技术有追求,正在苦苦针扎在架构师道路的程序员。如果你也有热爱技术或者怀有当架构师的理想不妨关注我,让我们一路同行,见证彼此的努力。微信搜索公众号"爱笑的架构师",等你~

首先引入一个实际的例子,我们常常会写一个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();            }        }    }  }
观察上面的两个方法可以发现,除了
return session.selectOne("com.coderspace.mapper.student.queryOne", id);
int rows = session.insert("com.coderspace.mapper.student.insert", student);
这两行,其他的代码都是一样的,都是先获取session,然后执行核心操作,最后关闭session。
获取session和关闭session这段代码围绕着具体的核心操作代码,我们可以称这段代码为模板代码。
假如又来了一个需求,需要实现删除student方法,那么你肯定会copy上面的获取session和关闭session代码,这样做有太多重复的代码,作为一名优秀的工程师肯定不会容忍这种事情的发生。
怎么解决呢?现在请出我们的主角:环绕执行模式使行为参数化。啥叫行为参数化?上面例子中我们已经观察到了,除了核心操作代码其他代码都是一模一样,那我们是不是可以将核心操作代码作为入参传入模板方法中,根据不同的行为分别执行。变量对象很容易作为参数传入,行为可以采用lambda表达式传入。
下面开始重构之前的例子,主要可以分为三步:
(1)定义函数式接口;
(2)定义模板方法;
(3)传递lambda表达式
所有的环绕执行模式都可以套用上面这三步公式。
第一步:定义函数式接口
@FunctionalInterface public interface DbOperation<R> {    /**     * 通用操作数据库接口     * @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<R> {        public R proccess(DbOperation<R> 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<Student> 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<Boolean> commonDao2 = new CommonDao<>(); // 使用lambda传递具体的行为 Boolean successInsert = commonDao2.proccess(        (session, mappperId, params) -> session.selectOne(mappperId, params),        mapperId2, student);
实现了上面三步,假如要实现删除方法,CommonDao里面一行代码都不用改,只用在调用方传入不同的参数即可实现。
环绕执行模式在现实环境中大有用途,如果你发现几行易变的代码外面围绕着一堆固定的代码,这个时候你应该考虑使用lambda环绕执行模式了。
精选文章:
xxx

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69984698/viewspace-2724777/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
博主从华中科技大学硕士毕业,曾浪迹于华为、百度大厂,是一个对技术有追求,正在苦苦针扎在架构师道路的程序员。如果你也有热爱技术或者怀有当架构师的理想不妨关注我,让我们一路同行,见证彼此的努力。微信搜索公众号"爱笑的架构师",等你~

注册时间:2020-09-28

  • 博文量
    6
  • 访问量
    4642