โ† Kembali ke Design Pattern
๐Ÿญ
Creational

Factory Method

Mendefinisikan interface untuk membuat objek, tetapi membiarkan subclass atau factory function menentukan class mana yang dibuat.

Masalahnya

Kode client butuh objek, tetapi tidak seharusnya terikat ke class konkretnya. Menulis `new ConcreteType()` di mana-mana membuat penggantian implementasi jadi merepotkan.

Cara Kerja

  • โ€บMemisahkan kode client dari implementasi class konkret
  • โ€บOpen/Closed: tipe produk baru bisa ditambahkan tanpa mengubah kode yang sudah ada
  • โ€บFactory menyimpan semua pengetahuan tentang class mana yang harus dibuat
  • โ€บBisa mengembalikan subclass berbeda berdasarkan parameter input
  • โ€บAbstract Factory memperluas ide ini dengan membuat keluarga objek yang saling terkait

Kapan Digunakan

โœ“Saat kamu belum tahu sebelumnya class mana yang akan dibuat
โœ“Saat logika pembuatan objek perlu dipusatkan dan dikontrol
โœ“Saat subclass yang seharusnya menentukan objek apa yang dibuat
โœ“Saat membuat objek dengan tipe berbeda berdasarkan konfigurasi runtime atau environment

Contoh di Dunia Nyata

๐ŸŽ
iOS

UITableView.dequeueReusableCell(withIdentifier:), UICollectionView cell registration

๐Ÿค–
Android

ViewModelProvider.Factory, RecyclerView.ViewHolder creation in onCreateViewHolder

๐ŸŒ
Web

React.createElement, document.createElement, Knex query builder

Contoh Kode

Swift
protocol Notification {
    func send(to recipient: String)
}

struct EmailNotification: Notification {
    func send(to recipient: String) { print("Email โ†’ \(recipient)") }
}

struct PushNotification: Notification {
    func send(to recipient: String) { print("Push โ†’ \(recipient)") }
}

struct SMSNotification: Notification {
    func send(to recipient: String) { print("SMS โ†’ \(recipient)") }
}

// Factory function
enum Channel { case email, push, sms }

func makeNotification(for channel: Channel) -> Notification {
    switch channel {
    case .email: return EmailNotification()
    case .push:  return PushNotification()
    case .sms:   return SMSNotification()
    }
}

let n = makeNotification(for: .push)
n.send(to: "agus@example.com")  // "Push โ†’ agus@example.com"