Java 中的流畅接口模式:使用流畅 API 增强代码表达力
大约 4 分钟
也称为
- 流畅 API
- 方法链
流畅接口设计模式的意图
流畅接口模式的主要目标是通过链接方法调用(通常称为方法链)提供易于阅读和流畅的 API。这种方法非常适合逐步构建复杂对象并改善整体开发体验。
使用真实世界示例详细解释流畅接口模式
真实世界示例
假设你在一家咖啡店逐步定制你的订单。这种方法类似于 Java 中流畅接口设计模式的工作原理,它允许你链接方法调用来按顺序构建和配置对象。你无需一次性告知咖啡师所有要求,而是以自然的方式逐个指定每个定制步骤。例如,你可以说:“我要一杯大杯咖啡,加两份浓缩咖啡,不加糖,最后淋上杏仁奶”。这种方法类似于流畅接口设计模式,你链接方法调用来以可读且直观的方式配置对象。就像你按顺序指定咖啡订单的每个部分一样,流畅接口允许你链接方法调用,从而在代码中逐步构建和配置对象。
简单来说
流畅接口模式为代码提供易于阅读的流畅接口。
维基百科说
在软件工程中,流畅接口是一种面向对象的 API,其设计依赖于方法链。它的目标是通过创建领域特定语言 (DSL) 来提高代码可读性。
Java 中流畅接口模式的编程示例
我们需要根据不同的标准从列表中选择数字。这是一个利用流畅接口模式来提供可读且易于使用的开发者体验的好机会。
在此示例中,给出了 FluentIterable
接口的两种实现。
public interface FluentIterable<E> extends Iterable<E> {
FluentIterable<E> filter(Predicate<? super E> predicate);
Optional<E> first();
FluentIterable<E> first(int count);
Optional<E> last();
FluentIterable<E> last(int count);
<T> FluentIterable<T> map(Function<? super E, T> function);
List<E> asList();
static <E> List<E> copyToList(Iterable<E> iterable) {
var copy = new ArrayList<E>();
iterable.forEach(copy::add);
return copy;
}
}
SimpleFluentIterable
积极地进行评估,对于真实世界的应用程序来说成本太高。
public class SimpleFluentIterable<E> implements FluentIterable<E> {
// ...
}
LazyFluentIterable
在终止时进行评估。
public class LazyFluentIterable<E> implements FluentIterable<E> {
// ...
}
它们的使用通过一个简单的数字列表来演示,该列表被过滤、转换和收集。结果之后被打印出来。
public static void main(String[] args) {
var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);
prettyPrint("The initial list contains: ", integerList);
var firstFiveNegatives = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(negatives())
.first(3)
.asList();
prettyPrint("The first three negative values are: ", firstFiveNegatives);
var lastTwoPositives = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(positives())
.last(2)
.asList();
prettyPrint("The last two positive values are: ", lastTwoPositives);
SimpleFluentIterable
.fromCopyOf(integerList)
.filter(number -> number % 2 == 0)
.first()
.ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber));
var transformedList = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(negatives())
.map(transformToString())
.asList();
prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
var lastTwoOfFirstFourStringMapped = LazyFluentIterable
.from(integerList)
.filter(positives())
.first(4)
.last(2)
.map(number -> "String[" + number + "]")
.asList();
prettyPrint("The lazy list contains the last two of the first four positive numbers "
+ "mapped to Strings: ", lastTwoOfFirstFourStringMapped);
LazyFluentIterable
.from(integerList)
.filter(negatives())
.first(2)
.last()
.ifPresent(number -> LOGGER.info("Last amongst first two negatives: {}", number));
}
程序输出
08:50:08.260 [main] INFO com.iluwatar.fluentinterface.app.App -- The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The first three negative values are: -61, -22, -87.
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The last two positive values are: 23, 2.
08:50:08.266 [main] INFO com.iluwatar.fluentinterface.app.App -- The first even number is: 14
08:50:08.267 [main] INFO com.iluwatar.fluentinterface.app.App -- A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- Last amongst first two negatives: -22
何时在 Java 中使用流畅接口模式
在以下情况下,使用 Java 中的流畅接口模式
- 设计使用频率高且客户端代码可读性非常重要的 API。
- 逐步构建复杂对象,并且需要使代码更加直观且不易出错。
- 增强代码清晰度并减少样板代码,尤其是在配置和对象构建场景中。
流畅接口模式 Java 教程
Java 中流畅接口模式的真实世界应用
- Java 8 Stream API
- Google Guava FluentIterable
- JOOQ
- Mockito
- Java Hamcrest
- 像 Apache Camel 这样的库中用于集成工作流程的构建器。
流畅接口模式的优点和权衡
优点
- 在你的 Java 项目中采用流畅接口模式可以显著提高代码可读性和可维护性。
- 鼓励构建不可变对象,因为方法通常返回新的实例。
- 减少了对变量的需求,因为上下文保存在链中。
权衡
- 对于那些不熟悉这种模式的人来说,可能会导致代码不太直观。
- 由于方法调用的链接,调试可能会很困难。
- 过度使用会导致复杂且难以维护的代码结构。
相关的 Java 设计模式
- 构建器:通常使用流畅接口来逐步构建对象。构建器模式侧重于构建复杂对象,而流畅接口则强调方法链机制。
- 责任链:流畅接口可以看作是责任链的具体应用,其中链中的每个方法都处理任务的一部分,然后委托给下一个方法。