问题
I am playing around with the Builder pattern and get stuck how to add a new "property" to a new-created object:
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:
MsProjectTaskData data = new MsProjectTaskData.Builder().withTransfered(true).build();
But with this approach the req
string from a new-created object is lost (of course).
Is there a possibility to create a new object with the new set isAlreadyTransfered
variable and with the "old" req
string from a "old" object?
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?
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?
回答1:
Make the Builder constructor take as an argument the "old" object and set whatever you want from it to the new one.
Edit
You need to read a bit more about the builder pattern to get a better grasp at what it is and if you really need it.
The general idea is that Builder pattern is used when you have optional elements. Effective Java Item 2 is your best friend here.
For your class, if you want to build one object from another and use a Builder pattern at the same time, you
- Either pass the "old" object in the Builder constructor
- Create a method from or fromOld, etc.
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
回答2:
I would change it to
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;
}
}
And used like this
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();
I took the liberty to change the boolean to "transfered", I feel it is easier to understand
来源:https://stackoverflow.com/questions/16216642/create-new-object-with-builder-pattern-with-old-object-reference