Abstract Factory Pattern — Design Patterns

Abstract Factory membuat keluarga object yang saling berkaitan tanpa menyebutkan class konkretnya. Cocok saat kamu punya beberapa "varian" produk yang harus kon

Abstract Factory membuat keluarga object yang saling berkaitan tanpa menyebutkan class konkretnya. Cocok saat kamu punya beberapa "varian" produk yang harus konsisten (misal semua komponen UI bertema gelap, atau semua komponen UI bertema terang).

Problem yang diselesaikan:

Misalkan kamu bikin UI toolkit cross-platform. Di Windows, tombol tampil dengan style A, checkbox style B. Di macOS, tombol tampil dengan style C, checkbox style D. Kamu tidak mau aplikasi tiba-tiba menggabungkan tombol Windows dengan checkbox macOS — keluarga harus konsisten.

Tanpa pattern, client code akan penuh kondisi if (platform === "windows") ... di setiap tempat object dibuat. Abstract Factory memindahkan semua pilihan ini ke satu factory per varian, lalu client cukup tanya "bikinin aku button dan checkbox" — factory yang memastikan semuanya bertema sama.

Factory Method vs Abstract Factory:

Implementasi minimal (JS/TS):

// 1. Produk-produk abstract (kontrak)
class Button {
  render() { throw new Error("abstract"); }
}
class Checkbox {
  render() { throw new Error("abstract"); }
}

// 2. Varian konkret — keluarga "Dark"
class DarkButton extends Button {
  render() { return "<button class='dark'>Click</button>"; }
}
class DarkCheckbox extends Checkbox {
  render() { return "<input type='checkbox' class='dark'>"; }
}

// 3. Varian konkret — keluarga "Light"
class LightButton extends Button {
  render() { return "<button class='light'>Click</button>"; }
}
class LightCheckbox extends Checkbox {
  render() { return "<input type='checkbox' class='light'>"; }
}

// 4. Abstract Factory — interface yang bikin sekeluarga produk
class UIFactory {
  createButton() { throw new Error("abstract"); }
  createCheckbox() { throw new Error("abstract"); }
}

// 5. Concrete Factory — satu per varian
class DarkUIFactory extends UIFactory {
  createButton() { return new DarkButton(); }
  createCheckbox() { return new DarkCheckbox(); }
}
class LightUIFactory extends UIFactory {
  createButton() { return new LightButton(); }
  createCheckbox() { return new LightCheckbox(); }
}

// 6. Client — cukup terima factory, tidak tahu varian apa
function renderLoginForm(factory) {
  const button = factory.createButton();
  const checkbox = factory.createCheckbox();
  return button.render() + checkbox.render();
  // Keluarga dijamin konsisten: Dark-Dark atau Light-Light
}

const theme = localStorage.getItem("theme") === "dark"
  ? new DarkUIFactory()
  : new LightUIFactory();
renderLoginForm(theme);

Pilihan varian hanya terjadi SEKALI di boot time, setelah itu client tinggal pakai factory.

Dunia nyata di ekosistem JS:

Kapan pakai:

Kapan JANGAN pakai:

Trade-off:

Kelebihannya: client loosely coupled ke produk konkret, konsistensi keluarga terjamin. Kekurangannya: banyak class (1 factory + N produk × M varian), dan menambah produk baru (misal Radio) mesti update semua factory — itu trade-off terbesar.

Yang akan kamu pelajari