Factory Pattern — Design Patterns

Factory Pattern menyediakan interface untuk membuat object tanpa menentukan class spesifik yang akan dibuat. Keputusan "object mana yang dibuat" ditangani…

Factory Pattern menaruh pembuatan object di satu function (disebut factory) yang memilih jenis object dari data yang diberikan, jadi pemanggilnya cukup bilang jenisnya tanpa tahu cara membuatnya. Bayangin loket ekspedisi. Kamu cukup bilang "kilat, 2 kilo". Petugas loket yang tahu tarifnya, estimasinya, dan stiker apa yang ditempel. Kamu gak perlu hafal tabel tarif. Factory adalah petugas loket itu di dalam kode.

🧪 Tebakan cepat: Kurir Kancil sudah membuat semua kiriman lewat createShipment yang membaca object SERVICES. Layanan baru sameday ditambahkan sebagai satu entri di SERVICES. Berapa file pemanggil (checkout, admin, API) yang harus ikut diubah? Tebak dulu, jawabannya ada di bagian "Versi lookup: satu entri per layanan".

Masalahnya: if yang disalin ke tiap pemanggil

Kurir Kancil membuat object kiriman di tiga tempat: halaman checkout, halaman admin, dan API untuk toko online. Tiap tempat menulis sendiri cabang per layanan:

// checkout.js (admin.js dan api.js punya salinan yang sama)
let shipment
if (service === "reguler") {
  shipment = { service: "reguler", kg, price: kg * 10000, eta: "3 hari" }
} else if (service === "kilat") {
  shipment = { service: "kilat", kg, price: kg * 18000, eta: "1 hari" }
}

Waktu layanan kargo datang, tiga file harus diubah. Satu terlupa, dan pesanan kargo dari file itu berhenti dengan TypeError: Cannot read properties of undefined (reading 'price'), karena shipment gak pernah diisi.

Factory function: satu tempat yang membuat object

function createShipment(service, kg) {
  let shipment

  if (service === "reguler") {
    shipment = { service: "reguler", kg, price: kg * 10000, eta: "3 hari" }
  } else if (service === "kilat") {
    shipment = { service: "kilat", kg, price: kg * 18000, eta: "1 hari" }
  } else if (service === "kargo") {
    shipment = { service: "kargo", kg, price: Math.max(kg, 10) * 6000, eta: "5 hari" }
  } else {
    throw new Error("Unknown service")
  }

  shipment.describe = function () {
    return this.service + " " + this.kg + " kg: Rp " + this.price
  }

  return shipment
}

console.log(createShipment("kilat", 2).describe()) // kilat 2 kg: Rp 36000
console.log(createShipment("kargo", 4).describe()) // kargo 4 kg: Rp 60000

Latihan nanti memakai bentuk yang sama dengan bangun datar: createShape(type, size) membuat lingkaran, persegi, atau segitiga, masing-masing dengan rumus luasnya, plus describe(). Untuk lingkaran, luasnya dibulatkan dengan toFixed(2): (Math.PI * 5 * 5).toFixed(2) menghasilkan teks "78.54", dua angka di belakang titik.

Versi lookup: satu entri per layanan

Rantai if masih harus diubah tiap ada layanan baru. Versi yang lebih ringkas menyimpan cara membuat tiap jenis di sebuah object, lalu memilih dengan kuncinya:

const SERVICES = {
  reguler: (kg) => ({ service: "reguler", kg, price: kg * 10000, eta: "3 hari" }),
  kilat: (kg) => ({ service: "kilat", kg, price: kg * 18000, eta: "1 hari" }),
  kargo: (kg) => ({ service: "kargo", kg, price: Math.max(kg, 10) * 6000, eta: "5 hari" }),
  sameday: (kg) => ({ service: "sameday", kg, price: kg * 25000, eta: "hari ini" }), // baru
}

function createShipment(service, kg) {
  if (!Object.hasOwn(SERVICES, service)) throw new Error("Unknown service")
  return SERVICES[service](kg)
}

Kapan gak perlu factory

⚠️ Jebakan yang sering ketemu

TL;DR: Factory Pattern menyembunyikan detail pembuatan object di satu function, dan memilih jenis object saat program berjalan dari data yang diberikan. createShipment(service, kg) punya satu cabang per layanan dengan rumusnya sendiri, menambahkan describe() (pakai function, supaya this adalah object-nya), dan menolak jenis yang gak dikenal dengan throw new Error(...). Versi lookup menyimpan tiap jenis sebagai entri di object, lalu memanggil SERVICES[service](kg): layanan baru cukup satu baris, pemanggil gak berubah. Cek kunci dengan Object.hasOwn. Kalau cuma ada satu jenis, factory belum perlu.

Yang akan kamu pelajari