如何为传递给方法的流畅 lambda 定义顺序
How to define an order for a fluent lambda passed to a method
在 this talk by venkat subramaniam 中,他制作了以下 Mailer 示例:
class Mailer {
public Mailer from(String addr) { System.out.println("from"); return this; }
public Mailer to(String addr) { System.out.println("to"); return this; }
public Mailer subject(String subjectLine) { System.out.println("subject"); return this; }
public Mailer body(String message) { System.out.println("body"); return this; }
public static void send(Consumer<Mailer> block) {
Mailer mailer = new Mailer();
block.accept(mailer);
System.out.println("sending...");
}
}
public class Sample {
public static void main(String[] args) {
Mailer.send(mailer -> {
mailer.from("builder@agiledeveloper.com")
.to("venkats@agiledeveloper.com")
.subject("Your code sucks")
.body("...");
});
}
}
对于这种特定情况,我知道实施细节可能没有意义,因为像这样的邮寄者不会关心订单,但如果我想强制执行您调用 from
的订单,to
、subject
和 body
这样你必须从 from
开始,然后是 to
,然后是 subject
然后是 body
怎么会我做这个?
我确实在 中看到了答案,但这依赖于使用 newBuilder
方法启动流程,我不确定如何将此模式应用于 lambda 示例。
尽管链接问题中的方法似乎不太适用于此,但可以对其进行一些调整以适合您的目的。
让我们首先添加链接问题中显示的类型:
interface IFromBuilder {
IToBuilder from(String from);
}
interface IToBuilder {
ISubjectBuilder to(String to);
}
interface ISubjectBuilder {
IBodyBuilder subject(String line);
}
interface IBodyBuilder {
void body(String body);
}
class Mailer implements IFromBuilder, IToBuilder, ISubjectBuilder, IBodyBuilder {
// implementations...
}
您使用的是接受 Consumer<Mailer>
的 send
方法,而不是 newBuilder
方法。取而代之的是,使用 Consumer<IFromBuilder>
public static void send(Consumer<IFromBuilder> block) {
Mailer mailer = new Mailer();
block.accept(mailer);
System.out.println("sending...");
}
如果你想强制开发人员每次都编写整个方法链,你可以这样做:
将方法链中的最后一个 return 改成另一种类型:
interface ICompletedMailer { // Mailer should also implement this
}
interface IBodyBuilder {
ICompletedMailer body(String body);
}
并将 Consumer<IFromBuilder>
更改为 Function<IFromBuilder, ICompletedMailer>
:
public static void send(Function<IFromBuilder, ICompletedMailer> block) {
Mailer mailer = new Mailer();
block.apply(mailer);
System.out.println("sending...");
}
在 this talk by venkat subramaniam 中,他制作了以下 Mailer 示例:
class Mailer {
public Mailer from(String addr) { System.out.println("from"); return this; }
public Mailer to(String addr) { System.out.println("to"); return this; }
public Mailer subject(String subjectLine) { System.out.println("subject"); return this; }
public Mailer body(String message) { System.out.println("body"); return this; }
public static void send(Consumer<Mailer> block) {
Mailer mailer = new Mailer();
block.accept(mailer);
System.out.println("sending...");
}
}
public class Sample {
public static void main(String[] args) {
Mailer.send(mailer -> {
mailer.from("builder@agiledeveloper.com")
.to("venkats@agiledeveloper.com")
.subject("Your code sucks")
.body("...");
});
}
}
对于这种特定情况,我知道实施细节可能没有意义,因为像这样的邮寄者不会关心订单,但如果我想强制执行您调用 from
的订单,to
、subject
和 body
这样你必须从 from
开始,然后是 to
,然后是 subject
然后是 body
怎么会我做这个?
我确实在 newBuilder
方法启动流程,我不确定如何将此模式应用于 lambda 示例。
尽管链接问题中的方法似乎不太适用于此,但可以对其进行一些调整以适合您的目的。
让我们首先添加链接问题中显示的类型:
interface IFromBuilder {
IToBuilder from(String from);
}
interface IToBuilder {
ISubjectBuilder to(String to);
}
interface ISubjectBuilder {
IBodyBuilder subject(String line);
}
interface IBodyBuilder {
void body(String body);
}
class Mailer implements IFromBuilder, IToBuilder, ISubjectBuilder, IBodyBuilder {
// implementations...
}
您使用的是接受 Consumer<Mailer>
的 send
方法,而不是 newBuilder
方法。取而代之的是,使用 Consumer<IFromBuilder>
public static void send(Consumer<IFromBuilder> block) {
Mailer mailer = new Mailer();
block.accept(mailer);
System.out.println("sending...");
}
如果你想强制开发人员每次都编写整个方法链,你可以这样做:
将方法链中的最后一个 return 改成另一种类型:
interface ICompletedMailer { // Mailer should also implement this
}
interface IBodyBuilder {
ICompletedMailer body(String body);
}
并将 Consumer<IFromBuilder>
更改为 Function<IFromBuilder, ICompletedMailer>
:
public static void send(Function<IFromBuilder, ICompletedMailer> block) {
Mailer mailer = new Mailer();
block.apply(mailer);
System.out.println("sending...");
}