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

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

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


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


01  引入实例


首先引入一个实际的例子,我们常常会写一个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代码,这样做有太多重复的代码,作为一名优秀的工程师肯定不会容忍这种事情的发生。


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


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


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


变量对象很容易作为参数传入,行为可以采用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环绕执行模式了。


相关文章
|
12天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
18天前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
20天前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
21天前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
30 4
|
25天前
|
Java API 开发者
Java中的Lambda表达式与函数式编程####
在Java的演变过程中,Lambda表达式和函数式编程的引入无疑是一次重大的飞跃。本文将深入探讨Lambda表达式的定义、用法及优势,并结合实例说明如何在Java中利用Lambda表达式进行函数式编程。通过对比传统编程方式,揭示Lambda表达式如何简化代码、提高开发效率和可维护性。 ####
|
4天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
18 0
|
1月前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
2月前
|
Java API
[Java]Lambda表达式
本文主要介绍了Java中的Lambda表达式,包括其优化匿名内部类的方式、使用规范、内置函数式接口及方法引用等内容。文章详细解析了Lambda的基础语法、参数列表、方法体的简化规则,以及如何利用Lambda优化代码。此外,还探讨了Lambda的作用域和引用规则,强调了对局部变量、成员变量和常量的访问限制,旨在帮助读者全面理解和掌握Lambda表达式的应用。
20 0
[Java]Lambda表达式
JAVA802_函数式接口的概述、Supplier供给型接口、consumer消费型接口、Predicate断定型接口、Function函数型接口(下)
③. consumer 只有输入,没有返回值 ④. Predicate有一个输入参数,返回boolean ⑤. Function:有一个输入参数,有一个输出
145 0
JAVA802_函数式接口的概述、Supplier供给型接口、consumer消费型接口、Predicate断定型接口、Function函数型接口(下)