几周前,我写了关于Java 8 lambda的介绍 。 在本简介中,我解释了什么是lambda以及如何将它们与Java 8中也引入的新Stream API结合使用。

Stream API为集合提供了更实用的接口。 此接口在很大程度上取决于lambda。 但是,lambda不仅具有改进的收集处理能力,还具有更多优势

Lambda为您提供了构建更流畅的API的机会。 为了说明这一点,作为示例,我喜欢使用UserStore ,它有助于使用数据库获取和保存用户。 它的公共API通常如下所示。

public interface UserStore {User find(Long id);List<User> findByLastname(String lastname);List<User> findByCompany(String company);..
}

findBy方法的列表通常比我在此处包括的两个方法更长。 随着系统的发展,可能还会有其他人。 尽管可行,但实际上所有这些方法都可以完成相同的事情。 他们返回具有匹配特定值的属性的所有用户。

一些框架提供了解决此问题的方法。 如果您使用过Hibernate,您可能会知道它们通过findByExample提供了解决方法,其中您提供了User作为示例对象,提供了查询的属性和值。 使用此示例对象中设置的任何值进行查询,而从查询中排除任何为null字段。 您可以稍微调整一下这种行为,但是这种方法存在许多问题。 考虑默认值,必填字段(即无法填写的字段)
null )和不变性。 iBatis,MyBatis以及Spring Data使用代码生成来节省您实现所有这些方法的时间,而使API充满了findBy方法列表。

这些变通办法可能会走很长一段路,但是它们确实留下了自己的特定问题。 另一种方法是使用lambda。

Lambda可以帮助我们将查询部分与过滤器规范分离。 让我们将findBy函数更改为接受lambda的单个函数。

public interface UserStore {User find(Long id);List<User> findBy(Predicate<User> p);
}

那是一个更好的API。 显然,谓词检查User对象有点天真。 您通常希望使用数据库查询进行过滤。 尽管如此,它仍然很好地满足了本示例的目的,您可以尝试使用自己的lambda来使用数据库查询进行过滤。 [注意: Predicate是Java 8附带的,位于java.util.function包中。

至少在以前的API中,这些谓词被捆绑在一个地方之前,您可能会生气,我们仍然可以捆绑(通用)谓词。 例如,通过创建一个包含它们的实用程序类UserPredicates

public final class UserPredicates {public static Predicate<User> lastname(String matcher) {return candidate -> matcher.equals(candidate.getLastname());}
}

使用新的UserStore API变得非常简单。

static import UserPredicates.lastname;userStore.findBy(lastname("<lastname>");

不过, UserStore中还有一件事确实让我感到困扰。 find(id)函数返回一个用户。 但是,如果没有这样的用户呢?

可选的

为了对此进行改进,我们可以(并且应该)查看Java 8的另一个新功能,Optional。 这是monad的Java实现。 它看起来很像Scala的Option

使用Optional我们可以更好地表示一个函数可以返回一个值,但不一定返回一个值,并防止使用null 。 在我们的find(id)示例中,返回Optional明确表示我们可能找到具有所请求ID的用户,但可能不存在这样的用户。

public interface UserStore {Optional<User> find(Long id);List<User> findBy(Predicate p);
}

该API现在不仅记录了您可能会获得用户的事实,而且从未返回null 。 我认为永不返回null的API更加安全。 有一天,一个新的程序员可能没有意识到find可以返回null并且结果是一个null指针异常。 只是希望团队能够在生产之前就抓住它。 只要不使用null ,就很容易防止空指针异常。

我们可以使用Optional上的函数从用户那里获取一个值(如果有的话),或者从一个默认值中获取一个值。 例如,为了安全地获取用户的姓氏,我们编写以下内容。

Optional<User> user = userStore.find(id);
String lastname = user.map(User::getLastname).orElse("");

这段代码表达力很强,不需要太多解释。 如果有用户,请获取其姓氏。 否则,获取一个空字符串。

如果我们需要向用户发送密码重置电子邮件(如果找到)怎么办?

Optional<User> user = userStore.find(id);
user.ifPresent(passwordReset::send);

如果找到用户,则发送密码重置,否则什么也没有发生。

由于Java不像其他可能提供的其他语言(例如Haskell,Clojure和Scala)那样支持解构,因此我们仅限于Optional的功能。 这使得Optional比任何一种其他语言的等效功能都弱。

建造者

当然,不仅存储库的API都可以从lambda中受益。 Optional也是受益于lambda的API的一个很好的示例。 就我个人而言,我还发现lambda特别有用,可以代替过去的过往建造者。 通常不通过将特定的构建器传递给函数,而是通过从函数中生成一个构建器来改善去耦。 让我向您展示一个示例,用于发送电子邮件以阐明该想法。

public interface Mailer {void sendTextMessage(TextMessageBuilder message);void sendMimeMessage(MimeMessageBuilder message);
}

要使用Mailer我们需要将特定的构建器传递给它。 这些构建器具有通用的界面,但是它们构建的消息类型不同。 Mailer具有不同的方法,因为它必须根据所使用的类型添加不同的信息。 因此,任何客户端代码都紧密耦合以传递正确的构建器。

您可能会怀疑,这是lambda有用的地方。 Mailer函数可以创建所需的生成器并将其产生给lambda,而不是要求客户端创建生成器并将其传递给客户端。

public interface Mailer {void sendTextMessage(MessageConfigurator configurator);void sendMimeMessage(MessageConfigurator configurator);@FunctionalInterfaceinterface MessageConfigurator {MessageBuilder configure(MessageBuilder message);}
}

要使用Mailer我们要做的就是提供一个lambda来构建消息。

mailer.sendTextMessage(message ->message.from(sender).to(recipients).subject("APIs").body("Lambdas can make for more fluent and stable APIs")
);

API现在更加稳定。 客户端代码与特定构建器中的任何更改都脱钩,并且只要构建器上的功能保持兼容就不会中断。

正如示例帮助我展示的那样,lambda可以帮助您构建更流畅和稳定的API,这些API更具意图。 这些API不需要太多的文档供其他程序员使用,因为实际上很难使它们弄错。 作为一般准则,我更喜欢清晰明了的代码而不是文档。 修复,不记录。

当然,我在本文中仅显示了一些示例。 Lambda不仅适用于此处的示例,而且适用范围更广。 我希望本文能为您提供一些有关lambda可以帮助您的新见解,并希望您能想到它们如何改善您的代码。

参考: Software Craft博客上的JCG合作伙伴 Bart Bakker 提供的Fluent和Stable API的Lambda 。

翻译自: https://www.javacodegeeks.com/2013/11/lambdas-for-fluent-and-stable-apis.html

流畅和稳定的API的Lambda相关推荐

  1. lambda 加和_流畅和稳定的API的Lambda

    lambda 加和 几周前,我写了关于Java 8 lambda的介绍 . 在本简介中,我解释了什么是lambda以及如何将它们与Java 8中也引入的新Stream API结合使用. Stream ...

  2. vMix解码16路FULL NDI时保持流畅和低带宽的使用方法和技巧(相当于16路采集卡同时工作,同步性和流畅度稳定,带宽占用率低,CPU和GPU负担小)

    vMix解码16路FULL NDI时保持流畅和低带宽的使用方法和技巧(相当于16路采集卡同时工作,同步性和流畅度稳定,带宽占用率低,CPU和GPU负担小) 很多朋友对NDI不了解,以为FULL NDI ...

  3. Java-常用API、Lambda、常见算法

    目录 一.日期与时间 1.Date 2.SimpleDateFormat 3.Calendar 二.JDK8新增日期类 1.概述.LocalTime/LocalDate/LocalDateTime 2 ...

  4. 包 权限修饰符 final 常量 枚举 抽象类 接口 多态 内部类 常用API 正则表达式 Lambda

    包 什么是包? 包是用来分门别类的管理各种不同类的,类似于文件夹.建包利于程序的管理和维护. 建包的语法格式:package 公司域名倒写.技术名称.报名建议全部英文小写,且具备意义. package ...

  5. 截至2019年11月份完全免费开放亲测可用稳定的API接口(持续更新中)

    搜索了一下网上的一些API接口,发现大多数都是过时的,不可用的,不再维护状态.我找了好久,终于找到一些最新的,实时更新的,可用稳定的一些API接口,全部总结在这里推荐给大家.欢迎大家多多关注. [ps ...

  6. JavaSE基础笔记——常用API、Lambda、常见算法

    日期与时间 时间日期是在任何一个程序系统里几乎都不可能忽略掉的数据量,而且大量的算法在底层都会使用到时间日期数据值作为算法的基本种子(随机数算法或加密算法都经常用到). 计算机里,时间日期的本质 作为 ...

  7. java less函数_AWS Serverless部署java api(LAMBDA篇)

    本文承接RDS for MySQL,前面我们已经部署好了数据库服务,并测试了连通性,这里则开始部署我们的代码,并连通rds服务. 可以以官方demo为例,或者引入aws提供的aws-serverles ...

  8. 好用实用稳定的API接口【物流快递篇】

    先来科普个概念,开放应用程序的API(即Application Program Interface,应用程序接口)可以让开发者在无需访问源码,或理解内部工作机制细节的情况下,调用他人共享的功能和资源. ...

  9. Java8新特性Stream API与Lambda表达式详解(1)

    2019独角兽企业重金招聘Python工程师标准>>> http://blog.csdn.net/caihuangshi/article/details/51298622 转载于:h ...

最新文章

  1. 简单粗暴的多对象目标跟踪神器 – DeepSort
  2. matlab中的科学记数法变成小数形式
  3. python与mysql数据库连接中常见错误
  4. 计算机培训研修日志,2021年计算机培训研修日志
  5. Maven高级之archetype(原型/骨架)开发
  6. 从计算机基础知识到机器学习第1堂课,最适合新手的5场直播来了
  7. linspace函数matlab_Matlab入门2-莫比乌斯环
  8. 操作自定义属性、H5自定义属性
  9. Python连接MySQL的实例代码
  10. linux 档案类型s,深入了解Linuxs归档和压缩命令 | MOS86
  11. 手机语音混响软件_Tone2 UltraSpace(音频混响软件)
  12. BScroll 实时监听滚动位置
  13. 友华PT921G光猫破解获取超级密码和更改桥接模式
  14. 电器元件——LM7805
  15. 【围棋游戏——使用Python实现(纯tkinter gui)】
  16. 网易云信 UI 开发
  17. wordpress php格式,PHP_WordPress自定义时间显示格式,在帮King改他的私人情侣博客模 - phpStudy...
  18. 2008年8月25号,星期一,晴。天将降大任于是人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为。
  19. 利用$randon和seed可以在测试脚本里面产生测试所需的赋值
  20. 三星电子在中国正式召开三星Galaxy Note20系列新品体验发布会~~~~

热门文章

  1. idea左右切换页面 返回上一次鼠标位置
  2. android手机打电话src,【SPILL 百科】SRC:Android 系统的 48kHz 音讯输出限制
  3. 计算机三级网络技术题库第15套,第15套 上机操作题
  4. Java BigDecimal和double区别
  5. jaxb注解使用_使用JAXB时
  6. spring mvc教程_Spring MVC教程
  7. kata_小规模流处理kata。 第1部分:线程池
  8. jvm 宕机 打印jvm_通过入侵JVM打印阵列
  9. java:退出功能_Java 8:功能VS传统
  10. 在Java中将时间单位转换为持续时间