Abstract Factory Pattern #
Dalam pengembangan software skala menengah hingga besar, kita sering berhadapan dengan kebutuhan untuk membuat keluarga objek (family of objects) yang saling berkaitan, namun ingin tetap menjaga kode agar tidak bergantung pada implementasi konkret. Di sinilah Abstract Factory Pattern berperan penting.
Abstract Factory adalah salah satu Creational Design Pattern yang berfokus pada cara membuat objek secara terstruktur, konsisten, dan mudah dikembangkan tanpa memodifikasi kode yang sudah ada.
Apa itu Abstract Factory Pattern? #
Abstract Factory Pattern adalah design pattern yang menyediakan interface untuk membuat sekumpulan objek terkait, tanpa harus menentukan kelas konkret dari objek-objek tersebut.
Alih-alih membuat objek langsung menggunakan new atau constructor, client hanya berinteraksi dengan factory abstraction.
“Create families of related or dependent objects without specifying their concrete classes.” — GoF
Tujuan Pattern #
Abstract Factory bertujuan untuk:
- Mengisolasi client dari concrete implementation
- Menjamin konsistensi antar objek dalam satu keluarga
- Mendukung Open/Closed Principle (mudah menambah variasi baru tanpa mengubah kode lama)
- Mengurangi coupling antara business logic dan object creation
Kapan Cocok Digunakan? #
Gunakan Abstract Factory jika:
- Aplikasi perlu bekerja dengan berbagai variasi produk (misalnya DB MySQL vs PostgreSQL)
- Objek-objek yang dibuat saling berkaitan dan harus konsisten
- Ingin mengganti seluruh keluarga objek tanpa mengubah client code
- Object creation logic mulai kompleks dan tersebar
Contoh Use Case Nyata #
- UI toolkit (Windows UI, Mac UI, Linux UI)
- Database driver abstraction
- Cloud provider abstraction (AWS, GCP, Azure)
- Payment gateway (Midtrans, Xendit, Stripe)
Struktur Pattern #
Secara umum terdiri dari:
- AbstractFactory → interface factory
- ConcreteFactory → implementasi factory spesifik
- AbstractProduct → interface produk
- ConcreteProduct → implementasi produk
- Client → menggunakan factory abstraction
Contoh Implementasi (Golang) #
Studi Kasus #
Kita ingin membuat Notification System yang mendukung:
- Email Notification
- SMS Notification
Setiap channel memiliki Sender dan Formatter yang harus konsisten.
Abstract Product #
type Sender interface {
Send(message string)
}
type Formatter interface {
Format(message string) string
}
Abstract Factory #
type NotificationFactory interface {
CreateSender() Sender
CreateFormatter() Formatter
}
Concrete Products – Email #
type EmailSender struct{}
func (e *EmailSender) Send(message string) {
println("Sending Email:", message)
}
// ---
type EmailFormatter struct{}
func (e *EmailFormatter) Format(message string) string {
return "[EMAIL] " + message
}
Concrete Products – SMS #
type SMSSender struct{}
func (s *SMSSender) Send(message string) {
println("Sending SMS:", message)
}
// ---
type SMSFormatter struct{}
func (s *SMSFormatter) Format(message string) string {
return "[SMS] " + message
}
Concrete Factories #
type EmailFactory struct{}
func (e *EmailFactory) CreateSender() Sender {
return &EmailSender{}
}
func (e *EmailFactory) CreateFormatter() Formatter {
return &EmailFormatter{}
}
type SMSFactory struct{}
func (s *SMSFactory) CreateSender() Sender {
return &SMSSender{}
}
func (s *SMSFactory) CreateFormatter() Formatter {
return &SMSFormatter{}
}
Client Code #
func Notify(factory NotificationFactory, message string) {
formatter := factory.CreateFormatter()
sender := factory.CreateSender()
formatted := formatter.Format(message)
sender.Send(formatted)
}
func main() {
emailFactory := &EmailFactory{}
smsFactory := &SMSFactory{}
Notify(emailFactory, "Welcome User")
Notify(smsFactory, "OTP Code 123456")
}
Kelebihan Abstract Factory #
✅ Konsistensi antar produk terjamin ✅ Mudah menambah keluarga produk baru ✅ Client code bersih dan tidak tahu detail implementasi ✅ Mendukung prinsip SOLID
Kekurangan Abstract Factory #
- ❌ Struktur kode lebih kompleks
- ❌ Menambah boilerplate (interface & factory)
- ❌ Kurang cocok untuk aplikasi kecil
Perbedaan dengan Factory Method #
| Factory Method | Abstract Factory |
|---|---|
| Fokus 1 produk | Fokus family produk |
| 1 method | Banyak method |
| Lebih simpel | Lebih fleksibel |
Best Practices #
Gunakan hanya jika memang ada lebih dari satu family objek Jangan over-engineering.
Factory jangan berisi business logic Fokus hanya pada object creation.
Kombinasikan dengan Dependency Injection Factory dipilih di composition root.
Naming yang jelas Contoh:
PaymentFactory,CloudResourceFactory.Hindari conditional di client Pemilihan factory sebaiknya dilakukan di awal aplikasi.
Penutup #
Abstract Factory Pattern sangat berguna ketika sistem Anda perlu mendukung berbagai variasi implementasi yang harus tetap konsisten satu sama lain. Pattern ini membantu menjaga arsitektur tetap bersih, scalable, dan mudah dikembangkan dalam jangka panjang.
Namun, seperti semua design pattern, gunakan dengan bijak. Jika kebutuhan belum kompleks, solusi sederhana sering kali lebih baik.
“Design patterns are not about using them everywhere, but knowing when you need them.”