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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16216642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 22:15:50  来源:igfitidea点击:

Create new object with Builder pattern with "old" object reference

javadesign-patternsbuilder

提问by sk2212

I am playing around with the Builder pattern and get stuck how to add a new "property" to a new-created object:

我正在尝试使用 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;
  }
}

I can create a new object with Builder like this:

我可以像这样用 Builder 创建一个新对象:

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

But with this approach the reqstring from a new-created object is lost (of course).

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

Is there a possibility to create a new object with the new set isAlreadyTransferedvariable and with the "old" reqstring from a "old" object?

是否有可能使用新的设置isAlreadyTransfered变量和来自“旧”对象的“旧”字符串创建新对象?req

Maybe I have to pass the old object reference to the Builder but I do not know how to do this. Maybe the use of Builder pattern is not really usefull for this approach?

也许我必须将旧对象引用传递给 Builder,但我不知道该怎么做。也许 Builder 模式的使用对于这种方法并不是真的有用?

EDIT: (After comment from Eugene)

编辑:(在尤金评论后)

Think, I got it:

想想,我明白了:

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

Seems to work or is something wrong with the code above? Can I use this approach without consideration?

似乎有效还是上面的代码有问题?我可以不加考虑地使用这种方法吗?

回答by Eugene

Make the Builder constructor take as an argument the "old" object and set whatever you want from it to the new one.

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

Edit

编辑

You need to read a bit more about the builder pattern to get a better grasp at what it is and if you reallyneed it.

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

The general idea is that Builder pattern is used when you have optionalelements. Effective Java Item 2 is your best friend here.

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

For your class, if you want to build one object from another and use a Builder pattern at the same time, you

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

  1. Either pass the "old" object in the Builder constructor
  2. Create a method fromor fromOld, etc.
  1. 在 Builder 构造函数中传递“旧”对象
  2. 创建一个方法fromfromOld等。

So how does that looks like? I am going to provide only the first one you can figure out the second on your own.

那么它看起来如何呢?我将只提供第一个,您可以自己找出第二个。

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

And how you will create one object from another:

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

   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