构建器模式:通过其他构建器创建的嵌套对象

时间:2015-10-19 09:59:29

标签: java design-patterns builder

假设我有两个对象,都是通过构建器模式创建的,另一个是嵌套到其他对象中:

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()方法中抛出了错误。

2 个答案:

答案 0 :(得分:2)

我会将Child个实例传递给Parent而不是ChildBuilder个实例。

如果您希望之后更改Child属性,则只需从ChildBuilder构建一个新的parentBuilder.child()

但是,当我看到所有这些建筑商时,我很关心设计。 DDD是关于无处不在的语言,“建设者”当然不是它的一部分。有时您无法在设计中引入技术概念,但我相信您可能会忘记其他可能有用的DDD构建块。

  

我到处都有建设者,因为我必须对每个人进行验证   应用中的域实体。例如,Parent的名称不长于   255,但对于不超过1000的孩子。 - Tahar Bakir(来自评论)

您在上面描述的规则可以封装并在构建时强制执行,例如ParentNameChildName,可以作为值对象实现。

您的ParentChild类可以使用这些概念而不是字符串。

答案 1 :(得分:1)

希望这有帮助

关于如何使用它的示例是在main方法中,这将打印 10 0

父类:

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());
  }
}

儿童班:

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);
    }
  }
}