Ini merupakan design pattern yang sangat populer digunakan. Software engineer yang menggunakan OOP harusnya pernah menggunakan atau setidaknya tahu tentang design pattern ini. Factory Method Design Pattern digunakan ketika ingin menggunakan implementasi objek tertentu tanpa harus tahu class-nya apa. Biasanya dengan cara tipe objek ditentukan berdasarkan input dari user. Jadi user ga perlu menggunakan new
operator, tapi factory class lah yang melakukannya. Design pattern ini termasuk yang paling mudah dipelajari karena cukup sederhana. Oh ya, jika masih ambigu tentang terminologi "Factory" dalam programming, bisa baca artikel Macam-macam Factory terlebih dahulu.
Factory Method Design Pattern adalah Creational Design Pattern yang menyediakan interface sebagai tempat pembuatan implementasi objek dari sebuah superclass.
Design Pattern
Use Case
Kita ingin membuat objek laptop berdasarkan merk laptop yang diinput dari request:
- Terdapat 2 jenis gaming laptop, yaitu Asus dan Dell;
- Ketika user mengirimkan request "asus", maka laptop yang didapatkan adalah Asus Rog;
- Ketika user mengirimkan request "dell", maka laptop yang didapatkan adalah Dell Alienware;
- Ketika user mengirimkan request yang salah, maka tampilkan error;
Contoh code
Laptop Interface
public interface Laptop{
String getLaptopName();
}
Class AsusRog
public class AsusRog implements Laptop{
@Override
public String getLaptopName(){
return "Asus ROG";
}
}
Class DellAlienware
public class DellAlienware implements Laptop{
@Override
public String getLaptopName(){
return "Dell Alienware";
}
}
Method buildLaptop()
public static Laptop buildLaptop(String laptop){
if("asus".equals(laptop)){
return new AsusRog();
}
if("dell".equals(laptop)){
return new DellAlienware();
}
throw new IllegalArgumentException("not found");
}
Contoh penggunaan
public static void main(String[] args){
Laptop laptop = buildLaptop("dell");
System.out.println("laptop.getLaptopName() = " + laptop.getLaptopName());
}
Pendekatan di atas disebut Simple Factory. Secara logic code di atas sudah memenuhi kriteria awal. Umumnya orang-orang menggunakan static method karena dapat digunakan dengan mudah.
Masalah
Masalah akan muncul ketika ada requirement baru, Asus dan Dell tidak hanya memproduksi Gaming Laptop doang. Mereka juga memproduksi Office Laptop dan Multimedia Laptop. Misalnya kalau untuk asus Office, implementasinya Asus Vivobook, untuk dell office, implementasinya Dell Latitude, dan semacamnya. Dengan code sebelumnya tentu saja akan rumit. Kemungkinan besar akan ada banyak branching if-else atau switch-case di dalamnya seperti "asus-gaming", "asus-office", "asus-multimedia", dan lainnya. Jika dibiarkan seperti itu maka method-nya akan gendut dan tentu saja bad practice.
Solusi
Sekarang ganti code di atas menggunakan Factory Method Pattern😎.
LaptopFactory Interface
public interface LaptopFactory{
Laptop buildLaptop(String laptop);
}
GamingLaptopFactory Class
public class GamingLaptopFactory implements LaptopFactory{
@Override
public Laptop buildLaptop(String laptop){
if("asus".equals(laptop)){
return new AsusRog();
}
if("dell".equals(laptop)){
return new DellAlienware();
}
throw new IllegalArgumentException("not found");
}
}
OfficeLaptopFactory class
public class OfficeLaptopFactory implements LaptopFactory{
@Override
public Laptop buildLaptop(String laptop){
if("asus".equals(laptop)){
return new AsusVivoBook();
}
if("dell".equals(laptop)){
return new DellLatitude();
}
throw new IllegalArgumentException("not found");
}
}
Contoh penggunaan
public static void main(String[] args){
LaptopFactory laptopFactory = new GamingLaptopFactory();
Laptop laptop = laptopFactory.buildLaptop("dell");
System.out.println("laptop.getLaptopName() = " + laptop.getLaptopName());
}
Method static buildLaptop() kita pindahkan ke dalam LaptopFactory. Sisanya code-nya masih sama dengan sebelumnya. Keuntungan dengan cara seperti ini adalah ketika ada jenis factory baru, misalnya OfficeLaptopFactory, kita tinggal bikin factory class baru dan implement LaptopFactory. Lalu lakukan hal yang sama, memasang-masangkan input user dengan objek Office Laptop yang dibutuhkan di dalam factory tersebut. Ketika butuh laptop office, tinggal gunakan implementasi OfficeLaptopFactory pada LaptopFactory. Dengan begitu factory-nya jadi lebih spesifik dan ga dibebankan ke satu method/class doang.
Kenapa menggunakan Factory Method Design Pattern?
Factory Method Design Pattern digunakan ketika ingin mendapatkan implementasi objek tertentu secara runtime berdasarkan input user. Jadi user cukup memberikan input yang diinginkan, lalu Factory Class akan memberikan implementasi objek sesuai yang diinginkan user. Umumnya sebelum menggunakan Factory Method Design Pattern, para developer menggunakan pendekatan Simple Factory terlebih dahulu. Simple Factory memang sangat simple, tapi tidak tahan perubahan ketika ada perubahan requirement. Apalagi seperti use case di atas, method akan sulit di-maintain jika tidak menggunakan Factory Method Design Pattern. Apalagi jika nanti requirement-nya berkembang yang mengharuskan kita upgrade menggunakan Abstract Factory Design Pattern.
Verdict
Factory Method Design Pattern merupakan design pattern yang sangat umum dan populer. Design pattern ini cukup mudah dipahami bagi newbie sekalipun. Dengan ini kita membungkus logic factory ke dalam sebuah interface agar fleksibel. Selain itu kita juga berhasil menerapkan Single Responsibility Principle dan Open/Closed Principle. Tapi jika jumlah implementasinya terus bertambah, code-nya juga bisa semakin rumit. Factory Method Pattern biasanya bisa berkembang nantinya menjadi Abstract Factory Design Pattern jika masing-masing factory memiliki komposisi yang spesifik tergantung requirement.