Java Fluent builder设计模式-如何强制客户设置变量
我对设计模式有问题。假设我有一个简单的类:Java Fluent builder设计模式-如何强制客户设置变量,java,design-patterns,builder,Java,Design Patterns,Builder,我对设计模式有问题。假设我有一个简单的类: public class Person { private String name; private String surname; private int age; private Person(){} public String toString() { return "name: "+name+" surname: "+surname+&
public class Person {
private String name;
private String surname;
private int age;
private Person(){}
public String toString()
{
return "name: "+name+" surname: "+surname+" age: "+age;
}
public static final class Builder{
private String name;
private String surname;
private int age;
public Builder name (String name){
this.name = name;
return this;
}
public Builder surname (String surname){
this.surname = surname;
return this;
}
public Builder age (int age){
this.age = age;
return this;
}
public Person build(){
Person person = new Person();
person.name=name;
person.surname=surname;
person.age=age;
return person;
}
}
}
它工作正常,但在调用“build”方法之前不需要设置变量。我怎样才能改变这一点呢?一种简单的强制方法是,如果没有设置所有设置,则在
build()
中抛出一个异常。连同文档,这可能已经足够了,但它不会提供任何编译时检查
另一种选择是,如果您对强制执行某些命令没有意见,可以使用“步骤”对象:
然后,使用情况需要如下所示:
Person p = Builder.name("John").surname("Smith").age(42).build();
姓名、姓氏和年龄都需要指定,而且在build()
可用之前都需要按此顺序指定
如果所有字段都是必填字段,您还可以删除build()
,创建Person
已在age(int)
中
还请注意,您可以直接将步骤放入Person
中,而不是将步骤放入Builder
中。静态“init”方法name(String)
已经创建了一个Person
实例,但它只有在调用age(int)
之后才能访问:
一个简单的方法是在
build()
中抛出一个异常,如果没有设置所有设置。连同文档,这可能已经足够了,但它不会提供任何编译时检查
另一种选择是,如果您对强制执行某些命令没有意见,可以使用“步骤”对象:
然后,使用情况需要如下所示:
Person p = Builder.name("John").surname("Smith").age(42).build();
姓名、姓氏和年龄都需要指定,而且在build()
可用之前都需要按此顺序指定
如果所有字段都是必填字段,您还可以删除build()
,创建Person
已在age(int)
中
还请注意,您可以直接将步骤放入Person
中,而不是将步骤放入Builder
中。静态“init”方法name(String)
已经创建了一个Person
实例,但它只有在调用age(int)
之后才能访问:
您可以通过做以下几件事来改进此代码:
公共类人物{
公众人物(字符串第一、字符串最后、整数){
this.first=first;
this.last=last;
这个。年龄=年龄;
}
}
if(年龄<0岁){
抛出新的IllegalArgumentException(“年龄不能为负:+Age”);
}
if(first==null&&last==null){
抛出新的IllegalArgumentException(“名字或姓氏为空”);
}
publicstaticbuilder someAdultPerson(){
归还新建筑商(“埃里卡”、“穆斯特曼”,18岁);
}
接口生成器{
T build();
静态给定(生成器){return Builder.build();}
}
...
班主任{
类生成器实现my.example.Builder{…}
}
...
导入static Person.Builder.someAdultPerson;
...
Person=给定的(某个成年人)年龄(27岁);
您可以通过做以下几件事来改进此代码:
公共类人物{
公众人物(字符串第一、字符串最后、整数){
this.first=first;
this.last=last;
这个。年龄=年龄;
}
}
if(年龄<0岁){
抛出新的IllegalArgumentException(“年龄不能为负:+Age”);
}
if(first==null&&last==null){
抛出新的IllegalArgumentException(“名字或姓氏为空”);
}
publicstaticbuilder someAdultPerson(){
归还新建筑商(“埃里卡”、“穆斯特曼”,18岁);
}
接口生成器{
T build();
静态给定(生成器){return Builder.build();}
}
...
班主任{
类生成器实现my.example.Builder{…}
}
...
导入static Person.Builder.someAdultPerson;
...
Person=给定的(某个成年人)年龄(27岁);
在用户可以调用build()
@BoristheSpider之前,您可以使用基于lambda的构建器强制执行一系列方法调用,因为构建器模式有很多不同的版本。你介意链接到你所指的那个吗?在用户调用build()
@borisspider之前,你可以使用基于lambda的构建器强制执行一系列方法调用,因为构建器模式有很多不同的版本。你介意链接到你指的那个吗?
//expanded to make it more obvious: the steps don't provide access to the Person until all have been executed
SurnameStep surnameStep = Person.name("John");
AgeStep ageStep = surnameStep .surname("Smith");
Person johnSmith = ageStep.age(42);