文章目录
【Java设计模式】流畅接口模式
一、概述
流畅接口模式的主要目标是通过链式方法调用提供一个易于阅读和流畅的API,通常称为方法链。这种方法非常适合逐步构建复杂对象,并改善整体开发人员体验。
二、别名
- 流畅API
- 方法链
三、流畅接口设计模式的意图
流畅接口设计模式的目的是通过方法链提供易于阅读和流畅的代码接口。
四、通过实际示例详细解释流畅接口模式
实际示例:
想象一下你在咖啡店逐步定制订单的过程。这种方式类似于Java中流畅接口设计模式的工作方式,允许你链式地调用方法来顺序地构建和配置对象。你不是一次性告诉咖啡师所有的要求,而是以一种自然流畅的方式逐步指定每个定制步骤。例如,你可能会说:“我想要一杯大杯咖啡,加两份浓缩咖啡,不加糖,顶部加杏仁奶。”这种方式类似于流畅接口设计模式,你通过链式方法调用以一种可读和直观的方式配置对象。就像你依次指定咖啡订单的每个部分一样,流畅接口允许你在代码中通过链式方法调用逐步构建和配置对象。
五、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("初始列表包含:", integerList);
var firstFiveNegatives = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(negatives())
.first(3)
.asList();
prettyPrint("前三个负数是:", firstFiveNegatives);
var lastTwoPositives = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(positives())
.last(2)
.asList();
prettyPrint("最后两个正数是:", lastTwoPositives);
SimpleFluentIterable
.fromCopyOf(integerList)
.filter(number -> number % 2 == 0)
.first()
.ifPresent(evenNumber -> LOGGER.info("第一个偶数是:{}", evenNumber));
var transformedList = SimpleFluentIterable
.fromCopyOf(integerList)
.filter(negatives())
.map(transformToString())
.asList();
prettyPrint("负数的字符串映射列表包含:", transformedList);
var lastTwoOfFirstFourStringMapped = LazyFluentIterable
.from(integerList)
.filter(positives())
.first(4)
.last(2)
.map(number -> "String[" + number + "]")
.asList();
prettyPrint("懒加载列表包含前四个正数中最后两个映射为字符串的数:", lastTwoOfFirstFourStringMapped);
LazyFluentIterable
.from(integerList)
.filter(negatives())
.first(2)
.last()
.ifPresent(number -> LOGGER.info("前两个负数中的最后一个是:{}", number));
}
程序输出:
08:50:08.260 [main] INFO com.iluwatar.fluentinterface.app.App -- 初始列表包含: 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 -- 前三个负数是: -61, -22, -87.
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- 最后两个正数是: 23, 2.
08:50:08.266 [main] INFO com.iluwatar.fluentinterface.app.App -- 第一个偶数是: 14
08:50:08.267 [main] INFO com.iluwatar.fluentinterface.app.App -- 负数的字符串映射列表包含: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- 懒加载列表包含前四个正数中最后两个映射为字符串的数: String[18], String[6].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- 前两个负数中的最后一个是: -22
六、何时在Java中使用流畅接口模式
在Java中使用流畅接口模式的时机包括:
- 设计被大量使用的API,并且客户端代码的可读性非常重要。
- 逐步构建复杂对象,并且需要使代码更直观、更不易出错。
- 增强代码清晰度并减少样板代码,特别是在配置和对象构建场景中。
七、流畅接口模式在Java中的实际应用
- Java 8 Stream API
- Google Guava FluentIterable
- JOOQ
- Mockito
- Java Hamcrest
- Apache Camel等库中的构建器用于集成工作流。
八、流畅接口模式的好处和权衡
好处:
- 在Java项目中采用流畅接口模式可以显著提高代码的可读性和可维护性。
- 鼓励构建不可变对象,因为方法通常返回新的实例。
- 由于上下文在链中维护,减少了对变量的需求。
权衡:
- 对于不熟悉该模式的人来说,可能会导致代码不太直观。
- 由于方法调用的链式结构,调试可能具有挑战性。
- 过度使用可能会导致复杂且难以维护的代码结构。