【发布时间】:2019-12-07 21:13:24
【问题描述】:
简介
在搜索网络时,我偶然发现了 Benoit Tellier 的一篇博文,Next level Java 8 staged builders,其中他分享了他针对某些用例的分阶段构建器模式的变体。
我注意到阶段用@FunctionalInterface 注释。这是他帖子中的一个例子(没有技术):
public static class MailboxCreatedBuilder {
@FunctionalInterface
public interface RequireUser {
RequireSessionId user(User user);
}
@FunctionalInterface
public interface RequireSessionId {
RequireMailboxId sessionId(MailboxSession.SessionId sessionId);
}
@FunctionalInterface
public interface RequireMailboxId {
FinalStage mailboxId(MailboxId mailboxId);
}
public static class FinalStage {
...
...
}
public static RequireUser builder() {
return user -> sessionId -> mailboxId -> new FinalStage(user, sessionId, mailboxId);
}
}
此注解将一个阶段可以拥有的方法数量限制为一个,以及具有默认实现的重载方法。无论如何,每个阶段都处理一个属性可能是一个好主意,但对于我目前的需求,我希望有多个方法在单独的类中实现。
问题
这让我想知道:我的舞台也应该有@FunctionalInterface 吗?在函数式编程中使用这样的构建器有什么好处/如何?
编辑
基于这个问题下面的 cmets,事实证明我真正想知道的是使阶段遵守功能接口合同的需求/好处是什么(不管可选注释)。
【问题讨论】:
-
具体来说,该注解只是为了确保每个阶段都有一个抽象方法,以便每个阶段都可以使用 lambda 实现。它是契约的一部分,可以为您节省实现单个类的代码,并告诉其他人您确实打算以这种方式工作。
-
阅读文章本身,我想说它本身就很好地概述了优点和缺点。从概念上讲,您不需要其中的任何内容,但是如果您想要像这样的分阶段构建器,那么按照我上面描述的方式进行注释会很有效。
-
啊,当然……所以否则这是不可能的:
return user -> sessionId -> mailboxId -> new FinalStage(user, sessionId, mailboxId);,对吧? -
不,您仍然可以从具有单一抽象方法且没有
@FunctionalInterface注释的接口制作 lambdas。该注释的作用是告诉您该接口确实打算只有一个方法,并且添加或删除非默认方法会破坏您的合同。该合约也将由编译器验证,因为 JLS 要求这样做。但是,如果RequireUser没有遵循函数式接口契约并且有两个抽象方法,则创建FinalStage的最后一个代码是不可能的。 -
我的意思是:为了使静态
builder()方法中的lamba 工作,阶段是否需要是功能接口(无论是否存在注释)?
标签: java functional-programming functional-interface