建造者模式:通过其他建造者创建的嵌套对象
Builder pattern: nested objects created through other builders
假设我有两个对象,都是通过构建器模式创建的,一个嵌套到另一个对象中:
class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public static class Builder {
private Child child;
public Builder() {}
public Builder child(Child child) {
this.child = child;
return this;
}
public Parent build() {
return new Parent(child);
}
}
}
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Parent build() {
return new Child(this);
}
}
}
所以,显而易见的用法非常简单:
Person.Builder parentBuilder = new Person.Builder().child(new Child.Builder().id(10).build());
制作
是不是很常见
public static class Builder {
private ChildBuilder child;
public Builder() {}
public Builder child(ChildBuilder child) {
this.child = child;
return this;
}
public Builder resetChildId() {
child.id(0);
return this;
}
public Parent build() {
Child childToPass = child.build();
return new Parent(childToPass);
}
}
这样以后仍然可以更新 child#id,但是由于延迟绑定,最近在 Parent.Builder#build() 方法期间抛出错误。
希望对您有所帮助
关于如何使用它的示例在 main 方法中,这将打印
10
0
parent class:
public class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public Child getChild(){
return this.child;
}
public static class Builder {
private Child.Builder childBuilder;
public Builder() {}
public Builder child(Child.Builder childBuilder) {
this.childBuilder = childBuilder;
return this;
}
public void resetChildId() {
childBuilder = childBuilder.id(0);
}
public Parent build() {
return new Parent(childBuilder.build());
}
}
public static void main (String[] args){
Parent.Builder parentBuilder = new Parent.Builder().child(new Child.Builder().id(10));
System.out.println(parentBuilder.build().getChild().getId());
//Reset the sucker
parentBuilder.resetChildId();
System.out.println(parentBuilder.build().getChild().getId());
}
}
child class:
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public long getId(){
return this.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Child build() {
return new Child(this);
}
}
}
我会将 Child
实例传递给 Parent
而不是 ChildBuilder
实例。
如果您希望之后更改 Child
属性,那么您只需从 parentBuilder.child()
.
构造一个新的 ChildBuilder
但是,当我看到所有这些构建器时,我对设计感到担忧。 DDD 是关于无处不在的语言,"builder" 当然不是它的一部分。有时您别无选择在设计中引入技术概念,但我相信您可能忘记了其他可能有帮助的 DDD 构建块。
I have builders everywhere because I have to do validation for each
domain entity in the app. For example name for Parent not longer than
255, but for child not more than 1000. - Tahar Bakir (from the comments)
您上面描述的规则可能会被封装并强制执行在域概念中的构造,例如 ParentName
和 ChildName
可以作为值对象实现。
您的 Parent
和 Child
类 然后可以使用这些概念而不是字符串。
假设我有两个对象,都是通过构建器模式创建的,一个嵌套到另一个对象中:
class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public static class Builder {
private Child child;
public Builder() {}
public Builder child(Child child) {
this.child = child;
return this;
}
public Parent build() {
return new Parent(child);
}
}
}
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Parent build() {
return new Child(this);
}
}
}
所以,显而易见的用法非常简单:
Person.Builder parentBuilder = new Person.Builder().child(new Child.Builder().id(10).build());
制作
是不是很常见public static class Builder {
private ChildBuilder child;
public Builder() {}
public Builder child(ChildBuilder child) {
this.child = child;
return this;
}
public Builder resetChildId() {
child.id(0);
return this;
}
public Parent build() {
Child childToPass = child.build();
return new Parent(childToPass);
}
}
这样以后仍然可以更新 child#id,但是由于延迟绑定,最近在 Parent.Builder#build() 方法期间抛出错误。
希望对您有所帮助
关于如何使用它的示例在 main 方法中,这将打印 10 0
parent class:
public class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public Child getChild(){
return this.child;
}
public static class Builder {
private Child.Builder childBuilder;
public Builder() {}
public Builder child(Child.Builder childBuilder) {
this.childBuilder = childBuilder;
return this;
}
public void resetChildId() {
childBuilder = childBuilder.id(0);
}
public Parent build() {
return new Parent(childBuilder.build());
}
}
public static void main (String[] args){
Parent.Builder parentBuilder = new Parent.Builder().child(new Child.Builder().id(10));
System.out.println(parentBuilder.build().getChild().getId());
//Reset the sucker
parentBuilder.resetChildId();
System.out.println(parentBuilder.build().getChild().getId());
}
}
child class:
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public long getId(){
return this.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Child build() {
return new Child(this);
}
}
}
我会将 Child
实例传递给 Parent
而不是 ChildBuilder
实例。
如果您希望之后更改 Child
属性,那么您只需从 parentBuilder.child()
.
ChildBuilder
但是,当我看到所有这些构建器时,我对设计感到担忧。 DDD 是关于无处不在的语言,"builder" 当然不是它的一部分。有时您别无选择在设计中引入技术概念,但我相信您可能忘记了其他可能有帮助的 DDD 构建块。
I have builders everywhere because I have to do validation for each domain entity in the app. For example name for Parent not longer than 255, but for child not more than 1000. - Tahar Bakir (from the comments)
您上面描述的规则可能会被封装并强制执行在域概念中的构造,例如 ParentName
和 ChildName
可以作为值对象实现。
您的 Parent
和 Child
类 然后可以使用这些概念而不是字符串。