Java 为方法调用调整生成器模式
这是为了理解《有效Java第二版》第40项:仔细设计方法签名的一部分 提高方法签名可读性的建议之一是针对四个或更少的参数。建议使用多种技术管理较长的参数列表,其中一种技术如下: 第三种结合前两种方法的技术是适应 从对象构造到方法的生成器模式(项目2) 调用。如果您有一个具有多个参数的方法,尤其是 其中一些是可选的,定义一个对象可能是有益的 表示所有参数,并允许客户端 此对象上的多个“setter”调用,每个调用设置一个 参数或一个小的相关组。一旦获得了所需的参数 设置后,客户机调用对象的“execute”方法,该方法 对参数进行任何最终有效性检查,并执行实际操作 计算 我熟悉用于对象构造的构建器模式,但不确定我是否正确理解了如何使其适应方法调用 以下是我迄今为止所做的:Java 为方法调用调整生成器模式,java,design-patterns,methods,builder,effective-java,Java,Design Patterns,Methods,Builder,Effective Java,这是为了理解《有效Java第二版》第40项:仔细设计方法签名的一部分 提高方法签名可读性的建议之一是针对四个或更少的参数。建议使用多种技术管理较长的参数列表,其中一种技术如下: 第三种结合前两种方法的技术是适应 从对象构造到方法的生成器模式(项目2) 调用。如果您有一个具有多个参数的方法,尤其是 其中一些是可选的,定义一个对象可能是有益的 表示所有参数,并允许客户端 此对象上的多个“setter”调用,每个调用设置一个 参数或一个小的相关组。一旦获得了所需的参数 设置后,客户机调用对象的“exe
(我已尝试改进
move
方法的方法调用)
我对Joshua Bloch建议的解释正确吗?在我看来,您的构建器类与父类关联(如与a关联),客户机会这样使用它:
Space space = new Space();
...
Space.MoveBuilder moveBuilder = space.new MoveBuilder(1, 1, -1);
moveBuilder.setTime(1234);
moveBuilder.execute();
可通过使用fluent builder和工厂方法进一步简化:
space.startMove(1, 1, -1).withTime(1234).endMove();
我已经使用在我想要实例化的类中定义的接口对构建器模式进行了具体化 有关此和相关“双向生成器”的更多信息,请参见此处: 我会做如下的事情;虽然这对于3个必填字段来说可能有些过分,但在考虑每个必填字段的同时,它对于构建更大的对象非常有帮助
public Class Space
{
public interface Builder
{
public Space build();
public int x();
public int y();
public int z();
}
// Build a complete Space object accounting for every field.
public Space(Space.Builder spaceBuilder)
{
this.x = spaceBuilder.x();
this.y = spaceBuilder.y();
this.z = spaceBuilder.z();
this.time = builder.time();
}
// Might not be necessar if you update time when you update x, y, and z
public Builder time(long val)
{
time = val;
return this;
}
public void move()
{
// ...
}
public static void main(String[] args)
{
new Builder()
{
@Override
public Space build(){ return new Space(this);}
@Override
public int x(){ return 1;}
@Override
public int y{ return 1;}
@Override int z{ return -1;}
}.build().time(1234).move();
}
}
我在编译时创建了它,生成调用方法的构建器。它还增加了对Java中方法参数默认值的支持
它可以在类或接口上使用。通过向类型添加@generateMethodIndivationBuilder
和@Default
注释
@GenerateMethodInvocationBuilder
public interface BitBucketServerService {
@GET("/rest/api/1.0/projects/{projectkey}/repos/{repositoryslug}/pull-requests?direction={direction}&at={at}&state={state}&order={order}&withattributes={withattributes}&withproperties={withproperties}")
Call<BitbucketServerResponse<BitBucketServerPullRequest>> pullRequests(//
@Default("PROJ") @Query("projectkey") String projectKey,//
@Default("REPO") @Query("repositoryslug") String repositoryslug,//
@Default("INCOMING") @Query("direction") String direction,//
@Default("23") @Query("at") String at,//
@Default("OPEN") @Query("state") String state,//
@Default("NEWEST") @Query("order") String order,//
@Default("true") @Query("withattributes") String withattributes,//
@Default("true") @Query("withproperties") String withproperties);
}
或设置您喜欢的任何参数:
BitBucketServerServicePullRequestsBuilder.pullRequests()
.withAt("24")
.invoke(bitBucketServerService);
更多关于GitHub的信息:啊,我本来想这么做的,但我忘记了。我打算搜索类似于JSFIDLE for java的东西,我认为这样做的想法是:
Builder=new MoveBuilder().x(123.y(456.time)(789);执行(生成器)代码>为什么在类空间中将x
、y
和z
声明为非final,在Builder
中声明为final?这真的没有道理。此外,您似乎根本不使用空间中的字段。这是Fluent Builder模式。为了进行比较,请查看一些众所周知的实现,如和。@AshutoshJindal如果某些参数是必需的,您确实可以将它们包含在构造函数中-或者您可以在execute
或build
中检查是否已设置所有必需参数,或者抛出IllegalArgumentException(例如)。如果有5个强制参数,将它们全部放在构造函数中会有点违背目标。是的,我同意非静态类更适合强调它与封闭类之间的绑定。
BitBucketServerServicePullRequestsBuilder.pullRequests()
.invoke(bitBucketServerService);
BitBucketServerServicePullRequestsBuilder.pullRequests()
.withAt("24")
.invoke(bitBucketServerService);