Recently, I've had a lot of opportunities to use the Effective Java Builder pattern mainly in Java, so I'll write it down for my own organization. It's just a simple summary.
For example, if you want to use OKHttpClient while developing Android,
OkHttpClient okHttpClient = new OkHttpClient();
And create an instance, but if you want to output the response to the log here
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
I will. Here is an example of a Builder pattern.
Normally, the class creates an instance by newing the user, but in the case of the Builder pattern, it is a little different.
I will prepare a static class in the class.
public class Example {
private int a;
private int b;
private int c;
private int d;
private int e;
public static class ExampleBuilder {
private int a;
private int b;
private int c;
private int d;
private int e;
}
}
Then, set a value in the field and grow a method that returns the Builder itself for each field.
public class Example {
private int a;
private int b;
private int c;
private int d;
private int e;
public static class ExampleBuilder {
private int a;
private int b;
private int c;
private int d;
private int e;
public Builder a(int a) {
this.a = a;
return this;
}
public Builder b(int b) {
this.b = b;
return this;
}
//c,d omitted
public Builder e(int e) {
this.e = e;
return this;
}
}
}
Meanwhile, at that time, we will prepare a private constructor for the Example class.
public class Example {
private int a;
private int b;
private int c;
private int d;
private int e;
//Builder omitted
private Example(Builder builder) {
this.a = builder.a;
this.b = builder.b;
this.c = builder.c;
this.d = builder.d;
this.e = builder.e;
}
}
The argument is the Builder created earlier, and I will pass that field to the Example field. Since it is an inner class, you can access the field directly.
And finally, implement the build method in the Builder.
public static class ExampleBuilder {
private int a;
private int b;
private int c;
private int d;
private int e;
public Builder a(int a) {
this.a = a;
return this;
}
public Builder b(int b) {
this.b = b;
return this;
}
//c,d omitted
public Builder e(int e) {
this.e = e;
return this;
}
public Example build() {
return new Example(this);
}
}
Since the argument this is the Builder itself, if the Builder is passed to the private constructor and the value is set in the field, the value will be set in the Example field.
With this, when you want to use Example,
Example example = new Example.Builder.a(1).b(2).c(3).d(4).e(5).build();
You can get an example with values set in all fields. If you set the field only in part
Example example = new Example.Builder.a(1).d(4).build();
It is okay to set only the required value.
I personally feel that the advantage of the Builder method is that ** the parameters passed to the constructor are easy to understand **.
The more arguments you pass to the constructor, the harder it is to see.
Example example = new Example(int aaaaaa, int bbbbbbb, int ccccccc, int ddddddd, int eeeeeeee);
If you implement it with the Builder pattern, readability will be improved because it is clearly stated what is set.
Also, if it is an optional parameter, you have to pass null one by one when not using it. There is also a method called the telescoping constructor pattern, in which multiple constructors are prepared, but it becomes difficult to read. If it is a Builder pattern, it is not necessary to set parameters that are not used, so the user does not have to be aware of it.
This time I wrote about the Effective Java Builder pattern, but I would like to write a lot about the GoF Builder pattern as well.
By Joshua Bloch Translated by Yoshiki Shibata Effective Java Second Edition
Recommended Posts