美文网首页Java8新特性
【Java8新特性】02 函数式接口和Lambda表达式实战练习

【Java8新特性】02 函数式接口和Lambda表达式实战练习

作者: 爱笑的架构师 | 来源:发表于2020-09-28 17:44 被阅读0次

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

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

    01  引入实例

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

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

    publicclassStudentDao{

    /**

        * 根据学生id查询记录

    *@paramid 学生id

    *@return返回学生对象

        */

    publicStudentqueryOne(intid){

            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

    SqlSession session =null;

    try{

                session = sqlSessionFactory.openSession();

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

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

    }finally{

    if(session !=null) {

                    session.close();

                }

            }

        }

    /**

        * 插入一条学生记录

    *@paramstudent 待插入对象

    *@returntrue if success, else return false

        */

    publicbooleaninsert(Student student){

            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

    SqlSession session =null;

    try{

                session = sqlSessionFactory.openSession();

    // 向数据库插入student对象

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

    returnrows >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代码,这样做有太多重复的代码,作为一名优秀的工程师肯定不会容忍这种事情的发生。

    02  环绕执行模式使行为参数化

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

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

    变量对象很容易作为参数传入,行为可以采用lambda表达式传入。

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

    (1)定义函数式接口;

    (2)定义模板方法;

    (3)传递lambda表达式

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

    第一步:定义函数式接口

    @FunctionalInterface

    publicinterfaceDbOperation{

    /**

        * 通用操作数据库接口

    *@paramsession 数据库连接session

    *@parammapperId 关联mapper文件id操作

    *@paramparams 操作参数

    *@return返回值,R泛型

        */

    Roperate(SqlSession session, String mapperId, Object params);

    }

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

    第二步:定义模板方法

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

    publicclassCommonDao{

    publicRproccess(DbOperation<R> dbOperation, String mappperId, Object params){

            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

    SqlSession session =null;

    try{

                session = sqlSessionFactory.openSession();

    // 核心操作

    returndbOperation.operate(session, mappperId, params);

    }finally{

    if(session !=null) {

                    session.close();

                }

            }

        }

      }

    第三步:传递lambda表达式

    // 根据id查询学生

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

    intstudentNo =123;

    CommonDao commonDao =newCommonDao<>();

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

    Student studentObj = commonDao.proccess(

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

            mapperId, studentNo);

    // 插入学生记录

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

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

    CommonDao commonDao2 =newCommonDao<>();

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

    Boolean successInsert = commonDao2.proccess(

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

            mapperId2, student);

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

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

    相关文章

      网友评论

        本文标题:【Java8新特性】02 函数式接口和Lambda表达式实战练习

        本文链接:https://www.haomeiwen.com/subject/vjqjuktx.html