使用带有"旧"对象引用的Builder模式创建新对象

sk2*_*212 6 java design-patterns builder

我正在使用Builder模式并且遇到如何向新创建的对象添加新的"属性":

public class MsProjectTaskData {
  private boolean isAlreadyTransfered;
  private String req;    

   public static class Builder {    
    private boolean isAlreadyTransfered = false;

    public Builder withTransfered(boolean val) {
        isAlreadyTransfered = val; 
        return this;
    }    
    public MsProjectTaskData build() {
        return new MsProjectTaskData(this);
    }
   }

   private MsProjectTaskData(Builder builder) {
     isAlreadyTransfered = builder.isAlreadyTransfered;
   }

  public MsProjectTaskData(String req) {
    this.req = req;
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用Builder创建一个新对象:

MsProjectTaskData data = new MsProjectTaskData.Builder().withTransfered(true).build();
Run Code Online (Sandbox Code Playgroud)

但是使用这种方法,req新创建的对象中的字符串会丢失(当然).

是否有可能使用新的set isAlreadyTransfered变量和"旧"对象中的"旧" 字符串创建新对象?req

也许我必须将旧的对象引用传递给Builder,但我不知道如何做到这一点.也许使用Builder模式对这种方法不是很有用吗?

编辑:(在Eugene发表评论后)

想想,我明白了:

public static class Builder {   
 private boolean isAlreadyTransfered = false;
 private MsProjectTaskData data;

 public Builder(MsProjectTaskData data) {
     this.data = data;
 }

 public Builder withTransfered(boolean val) {
     isAlreadyTransfered = val; 
     data.setAlreadyTransfered(isAlreadyTransfered);
     return this;
 }   
 public MsProjectTaskData build() {
     return data;
 }
}
Run Code Online (Sandbox Code Playgroud)

似乎工作或上面的代码有问题?我可以不经考虑使用这种方法吗?

Eug*_*ene 15

使Builder构造函数将"旧"对象作为参数,并将您想要的任何内容设置为新对象.

编辑

您需要阅读有关构建器模式的更多信息,以便更好地掌握它是什么以及是否真的需要它.

一般的想法是,当您有可选元素时使用Builder模式.有效的Java Item 2是你最好的朋友.

对于您的类,如果您想要从另一个对象构建一个对象并同时使用Builder模式,那么您

  1. 在Builder构造函数中传递"旧"对象
  2. 创建方法源自古

那看起来怎么样?我将只提供你可以自己弄清第二个的第一个.

class MsProjectTaskData {
    private final String firstname;
    private final String lastname;
    private final int age;

    private MsProjectTaskData(Builder builder){
        this.firstname = builder.firstname;
        this.lastname  = builder.lastname;
        this.age       = builder.age;
    }

    public static final class Builder{
        //fields that are REQUIRED must be private final
        private final String firstname;
        private final String lastname;

        //fields that are optional are not final
        private int age;

        public Builder(String firstname, String lastname){
            this.firstname = firstname;
            this.lastname  = lastname;
        }

        public Builder(MsProjectTaskData data){
            this.firstname = data.firstname; 
            this.lastname  = data.lastname;
        }

        public Builder age(int val){
            this.age = val; return this;
        }

        public MsProjectTaskData build(){
            return new MsProjectTaskData(this);
        }
    }

    public String getFirstname() {
         return firstname;
    }

    public String getLastname() {
         return lastname;
    }

    public int getAge() {
         return age;
    }
}
Run Code Online (Sandbox Code Playgroud)

以及如何从另一个创建一个对象:

   MsProjectTaskData.Builder builder = new MsProjectTaskData.Builder("Bob", "Smith");
   MsProjectTaskData oldObj = builder.age(23).build();
   MsProjectTaskData.Builder newBuilder = new MsProjectTaskData.Builder(oldObj);
   MsProjectTaskData newObj = newBuilder.age(57).build();
   System.out.println(newObj.getFirstname() + " " + newObj.getLastname() + " " + newObj.getAge()); // Bob Smith 57
Run Code Online (Sandbox Code Playgroud)