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

时间:2013-04-25 13:53:31

标签: 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;
  }
}

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

MsProjectTaskData data = new MsProjectTaskData.Builder().withTransfered(true).build();

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

是否有可能使用新设置的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;
 }
}

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

2 个答案:

答案 0 :(得分:14)

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

修改

您需要阅读有关构建器模式的更多信息,以便更好地了解构建器模式,以及确实需要它。

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

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

  1. 在Builder构造函数
  2. 中传递“旧”对象
  3. 从或 fromOld 等创建方法
  4. 那怎么样?我将只提供你可以自己弄清第二个的第一个。

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

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

       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
    

答案 1 :(得分:-1)

我会把它改成

   public class MsProjectTaskData {
    private boolean transfered;
    private String request;    

    public static class Builder {    
        private boolean transfered = false;
        private String request;

        public Builder() {
            // empty
        }

        public Builder(MsProjectTaskData old) {
            this.request(old.request);
            this.transfered(old.transfered);
        }

        public Builder request(String val) {
            request = val; 
            return this;
        }

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

    private MsProjectTaskData(Builder builder) {
        transfered = builder.transfered;
        request = builder.request;
    }

}

并像这样使用

MsProjectTaskData data = new  MsProjectTaskData.Builder().transfered(true).request("request").build();
MsProjectTaskData changedData = new MsProjectTaskData.Builder(data).transfered(false).request("changeRequest").build();
MsProjectTaskData sameData = new MsProjectTaskData.Builder(data).build();

我冒昧地将布尔值更改为“已转移”,我觉得它更容易理解