溶液
构建这种流畅的 API 模式的一个好方法是,不要只从每个方法返回,而是返回一个实例,该实例实现的 a 仅支持应位于列表中的方法,并让最后一个方法调用返回您需要的实际对象。this
Method Object Pattern
Interface
next
如果这是获取该对象实例的唯一方法,则始终必须调用最后一种方法。
package com.stackoverflow;
import javax.annotation.Nonnull;
import java.util.Date;
public class Q6613429
{
public static void main(final String[] args)
{
final Rights r = PermissionManager.grantUser("me").permissionTo("ALL").item("EVERYTHING").asOf(new Date());
PermissionManager.apply(r);
}
public static class Rights
{
private String user;
private String permission;
private String item;
private Date ofDate;
private Rights() { /* intentionally blank */ }
}
public static class PermissionManager
{
public static PermissionManager.AssignPermission grantUser(@Nonnull final String user)
{
final Rights r = new Rights(); return new AssignPermission() {
@Override
public AssignItem permissionTo(@Nonnull String p) {
r.permission = p;
return new AssignItem() {
@Override
public SetDate item(String i) {
r.item = i;
return new SetDate()
{
@Override
public Rights asOf(Date d) {
r.ofDate = d;
return r;
}
};}
};}
};
}
public static void apply(@Nonnull final Rights r) { /* do the persistence here */ }
public interface AssignPermission
{
public AssignItem permissionTo(@Nonnull final String p);
}
public interface AssignItem
{
public SetDate item(String i);
}
public interface SetDate
{
public Rights asOf(Date d);
}
}
}
这强制执行了构造调用链,并且对代码完成非常友好,因为它显示了下一个接口是什么,并且只有方法可用。
下面是一个更完整的示例,中间是可选内容:
UrlBuilder.java
这提供了一种万无一失的检查异常免费方法来构造对象。URL
将持久性与构造混合在一起是混合问题:
创建对象和存储对象是不同的关注点,不应混合使用。考虑到这并不意味着,反之亦然,并指出关注点的混合立即在不同的地方做不同的事情,你得到你想要的保证。.build()
.store()
buildAndStore()
将对持久性代码的调用放在另一个方法中,该方法仅接受 完全构造的 实例。Rights