Reputation: 405
Am I still following the Builder pattern with the implementation below? What's confusing me is the protected constructor in the class "myClass". My first thought when it comes to the builder pattern is to hide the object that the builder is supposed to construct. But here we don't. I can't understand if this is just bad design or ok design.
public class MyClass{
private final String x;
private final String y;
protected MyClass(MyBuilder builder){
this.x = builder.getX();
this.y = builder.getY();
}
//getters...
}
public class MyBuilder{
private String X;
private String Y;
public MyBuilder withX(String x){
this.x = x;
return this;
}
public MyBuilder withY(String y){
this.y = y;
return this;
}
public MyClass build(){
return new MyClass(this);
}
//getters....
}
public class Main{
public static void main(){
//Example 1
MyClass myClass = new MyBuilder().withX("x").withY("y").build();
//Example 2
MyClass myClass2 = new MyClass(new MyBuilder().withX("x").withY("y"));
}
}
Upvotes: 0
Views: 4045
Reputation: 4218
The constructor is protected
in order to restrict the possibilty of creating new instances of myClass
outside the protected scope.
This looks a bit strange because usually a builder uses private
constructor to totally avoid the creation of the instance by the client code without using the builder.
If you really want to hide the constructor of the class to build, you can create your builder as an inner class of the class to build :
public static class MyClass{
private final String x;
private final String y;
private MyClass(MyBuilder builder){
this.x = builder.x;
this.y = builder.y;
}
public static class MyBuilder{
private String x;
private String y;
public MyBuilder(){
}
public MyClass build() {
return new MyClass(this);
}
public MyBuilder withX(String x){
this.x = x;
return this;
}
public MyBuilder withY(String y){
this.y = y;
return this;
}
}
}
In this case the only way to create a new instance is using the builder, because the constructor of MyClass
is now private.
MyClass myClass = new MyBuilder().withX("xXx").withY("yYy").build();
Upvotes: 4
Reputation: 13765
Different than builder implementations that I've seen (not saying it wouldn't work though). The protected constructor confuses me as well. How would this get called unless you've created another class which extended myClass
? At which point your builder might function differently for the extended class.
I'm used to using fluent builders that return an instance of the object it's building, but maybe that's just my preference.
Class to build:
public class myClass{
private final String x;
private final String y;
public myClass(String x, String y){
this.x = x;
this.y = y;
}
}
Builder:
public class myBuilder{
private String X = "Default X";
private String Y = "Default Y";
public myBuilder withX(String x){
this.x = x;
return this;
}
public myBuilder withY(String y){
this.y = y;
return this;
}
public myClass build(){
return new myClass(y, x);
}
}
Calling:
new myBuilder().withX("x").withY("y").build();
returns new myClass
with x
= "x" and y
= "y"
new myBuilder().build();
returns new myClass
with x
= "Default X" and y
= "Default Y"
Upvotes: 0