![Contoh Builder Design Pattern](https://images.ctfassets.net/7wjlcr9d5ii8/4VaJesWWBmXC7tBVuvOQP0/8d5a55c62c064d92242ac33e50a83252/OIG3.jpg?w=1024&h=1024&fl=progressive&q=100&fm=jpg&fit=thumb&f=faces)
Biasanya ketika membuat objek, kita tinggal menggunakan keyword 'new' yang dilanjutkan dengan nama constructor yang mau dibikin. Namun kadang ada beberapa kasus yang membuat kita ga semudah itu dalam membuat objek, seperti ketika menggunakan immutable object. Design Pattern yang satu ini menurut gw yang paling gampang dikuasai, walaupun penerapannya agak kompleks dikit. Penggunaannya gw rasa juga sudah sangat umum. Gw juga udah sering memberikan contoh code menggunakan Builder Pattern ini, salah satunya pada post tentang Java: The Verbosity
Builder Design Pattern adalah Creational Design Pattern yang membuat kita bisa bikin objek yang kompleks secara step by step melalui konstruksi code yang sama.
Design Pattern
Kita ingin membuat sebuah objek dengan spesifikasi seperti berikut:
- Buat objek Teacher dengan property id, name, email, birthDate, dan address;
- Objek tersebut immutable, sehingga setelah dibuat, property dari objek tersebut tidak bisa diganti lagi;
Teacher Class
public class Teacher{
private final int id;
private final String name;
private final String email;
private final LocalDate birthDate;
private final String address;
public Teacher(int id, String name, String email, LocalDate birthDate, String address){
this.id = id;
this.name = name;
this.email = email;
this.birthDate = birthDate;
this.address = address;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
public String getEmail(){
return email;
}
public LocalDate getBirthDate(){
return birthDate;
}
public String getAddress(){
return address;
}
}
Contoh penggunaan
public static void main(String[] args){
Teacher teacher = new Teacher(1, "ferry", "ff@ff.com", LocalDate.of(2005, 12, 30), "Solok");
System.out.println("teacher.getName() = " + teacher.getName());
}
Pada code di atas, kita telah membuat immutable object dengan benar.
Yang jadi permasalahan adalah kita harus hafal urutan parameter constructor, karena pada Java pembuatan objek lewat constructor itu tidak fleksibel. Posisi parameternya rentan tertukar. Belum lagi jika ada perubahan, tiap perubahan tentu akan memodifikasi constructor sebelumnya. Baru 5 property, bagaimana jika ada 10 property? Makin rumit pemakaiannya😩.
Sekarang kita coba implementasikan Builder Pattern😎.
TeacherBuilder Class
public class TeacherBuilder{
private int id;
private String name;
private String email;
private LocalDate birthDate;
private String address;
public TeacherBuilder(){
}
public TeacherBuilder id(int id){
this.id = id;
return this;
}
public TeacherBuilder name(String firstName){
this.name = firstName;
return this;
}
public TeacherBuilder email(String email){
this.email = email;
return this;
}
public TeacherBuilder birthDate(LocalDate birthDate){
this.birthDate = birthDate;
return this;
}
public TeacherBuilder address(String address){
this.address = address;
return this;
}
public Teacher build(){
return new Teacher(id, name, email, birthDate, address);
}
}
Contoh penggunaan
public static void main(String[] args){
Teacher teacher = new TeacherBuilder()
.name("ferry")
.birthDate(LocalDate.of(2005, 12, 30))
.address("Solok")
.email("ff@ff.com")
.id(1)
.build();
System.out.println("teacher.getName() = " + teacher.getName());
}
Dengan builder class, kita bisa mengatur propertinya di urutan manapun selama objeknya belum di-build.
Hal seperti di atas dapat diakali dengan library Project Lombok. Sehingga ga perlu lagi capek-capek bikin Builder Class untuk setiap class yang immutable. Cukup tambahkan annotasi @Builder dan @Value langsung jadi.
Teacher Class
@Builder(toBuilder = true)
@Value
public class Teacher{
int id;
String name;
String email;
LocalDate birthDate;
String address;
}
Contoh penggunaan
public static void main(String[] args){
Teacher teacher = Teacher.builder()
.name("ferry")
.birthDate(LocalDate.of(2005, 12, 30))
.address("Solok")
.email("ff@ff.com")
.id(1)
.build();
System.out.println("teacher.getName() = " + teacher.getName());
}
Di dalam annotasi @Builder juga ada parameter toBuilder, yang mana jika itu true, kita dapat mengkonversi kembali objek tersebut kembali menjadi builder objek untuk di-rekonstruksi lagi menjadi objek yang baru. Jadi property objek yang lama akan di-copy ke property objek yang baru. Objek yang lama tetap immutable.
Contoh penggunaan toBuilder
public static void main(String[] args){
Teacher teacher = Teacher.builder()
.name("ferry")
.birthDate(LocalDate.of(2005, 12, 30))
.address("Solok")
.email("ff@ff.com")
.id(1)
.build();
System.out.println("teacher.getName() = " + teacher.getName());
Teacher suhandri = teacher.toBuilder().name("suhandri").build();
System.out.println("suhandri.getName() = " + suhandri.getName());
System.out.println("teacher.getName() = " + teacher.getName());
}
Seperti yang sudah diungkapkan di atas, Builder Pattern seringkali cocok digunakan untuk kasus yang memerlukan immutable object agar pembuatan objeknya tidak rumit dan fleksibel. Tapi tidak semua kasus cocok menggunakan design pattern ini. Contohnya untuk objek yang hanya memiliki satu atau dua property, menggunakan Builder Pattern tentu terlalu overkill. Builder Pattern juga punya kelemahan, yaitu semua property-nya jadi ga wajib diisi by default. Akan bermasalah biasanya ketika lupa diisi valuenya saat construct builder. Otomatis property-nya null dan ga bisa dimodifikasi karena immutable kecuali dengan bikin objek baru. Misalkan ada requirement seperti ini: property id dan name itu wajib diisi, sedangkan yang lainnya ga wajib. Untuk yang satu ini kita bisa memodifikasi Builder Pattern sebelumnya seperti berikut:
public class TeacherBuilder{
private final int id;
private final String name;
private String email;
private LocalDate birthDate;
private String address;
public TeacherBuilder(int id, String name){
this.id = id;
this.name = name;
}
public static TeacherBuilder builderWithIdAndName(int id, String name){
return new TeacherBuilder(id, name);
}
public TeacherBuilder email(String email){
this.email = email;
return this;
}
public TeacherBuilder birthDate(LocalDate birthDate){
this.birthDate = birthDate;
return this;
}
public TeacherBuilder address(String address){
this.address = address;
return this;
}
public Teacher build(){
return new Teacher(id, name, email, birthDate, address);
}
}
Contoh penggunaan
public static void main(String[] args){
Teacher teacher = TeacherBuilder.builderWithIdAndName(1, "ferry")
.birthDate(LocalDate.of(2005, 12, 30))
.address("Solok")
.email("ff@ff.com")
.build();
System.out.println("teacher.getName() = " + teacher.getName());
}
Dengan begitu, untuk menggunakan builder, kita harus mengisi id dan name terlebih dahulu sebelum mengisi property lainnya hingga akhirnya memanggil method build nantinya.
Builder Pattern merupakan Design Pattern yang paling gampang dipelajari meskipun penerapannya agak sedikit kompleks. Builder Pattern agak berbeda dengan design pattern lainnya karena tidak membutuhkan abstraksi. Builder pattern penggunaannya dapat dipermudah dengan menggunakan library Project Lombok. Tidak semua immutable object bisa diselesaikan dengan Builder Pattern, karena by default semua property-nya ga wajib diisi. Sehingga beberapa property yang wajib diisi harus dibuatkan algoritma khusus pada builder agar ga nullable. Penggunaan Builder Pattern pada objek dengan satu atau dua property juga terlalu overkill, disarankan untuk kasus seperti itu lebih baik menggunakan constructor biasa. Pada Java, kita juga mungkin udah sering menggunakan StringBuilder, StringBuffer, dan StringJoiner. Ketiganya juga termasuk Builder Pattern karena menghasilkan object String secara step by step.