Design pattern adalah cara menyelesaikan masalah desain kode yang sering muncul, yang sudah diberi nama dan sudah teruji di banyak project. Bayangin pola jahit di tukang jahit. Pola kerah kemeja dari kertas itu dipakai lagi untuk tiap pelanggan, cuma disesuaikan ukuran dan kainnya. Polanya bukan kemejanya. Design pattern juga begitu: dia bentuk solusinya, sedangkan kode yang kamu tulis adalah kemejanya, beda di tiap project.
🧪 Tebakan cepat: di kode Kurir Kancil versi pertama, layanan baru
samedayditambahkan ke fungsipricesaja, lupa ke fungsieta. Paket sameday 2 kg dicetak denganconsole.log("sameday:", price("sameday", 2), "rupiah,", eta("sameday")). Apa yang tercetak? Tebak dulu, jawabannya ada di bagian "Tiga kelompok pattern".
Contoh sepanjang track: Kurir Kancil
Sepanjang track ini kita merawat satu aplikasi: Kurir Kancil, jasa kirim paket kecil. Aplikasinya memberi nomor resi (KCL-0001, KCL-0002, ...), menghitung ongkir per layanan (reguler Rp 10.000 per kg sampai dalam 3 hari, kilat Rp 18.000 per kg sampai dalam 1 hari), dan mengabari pelanggan tiap status paket berubah: dijemput, transit, diantar, terkirim.
Versi pertamanya ditulis cepat, semua dalam satu file:
var lastResi = 0 // bisa dibaca dan diubah file mana pun
function nextResi() {
lastResi = lastResi + 1
return "KCL-" + String(lastResi).padStart(4, "0")
}
function price(service, kg) {
if (service === "reguler") return kg * 10000
if (service === "kilat") return kg * 18000
}
function eta(service) {
if (service === "reguler") return "3 hari"
if (service === "kilat") return "1 hari"
}
function updateStatus(parcel, status) {
parcel.status = status
sendSms(parcel) // tiap pihak baru yang perlu dikabari...
refreshTracking(parcel) // ...berarti satu baris baru di sini
}
Kodenya jalan. Masalahnya baru terasa waktu aplikasinya berubah: layanan baru harus ditambahkan di beberapa fungsi sekaligus, lastResi bisa tertimpa file lain, dan updateStatus harus diubah tiap ada pihak baru yang perlu dikabari. Tiap lesson berikutnya mengambil satu rasa sakit seperti ini dan menyembuhkannya dengan satu pattern.
Pattern itu pola, bukan potongan kode
Satu pattern punya empat bagian: nama, masalah yang dia selesaikan, bentuk solusinya, dan harganya (kode jadi punya lebih banyak bagian dan nama). Kodenya sendiri gak pernah persis sama. Contohnya pattern Observer: "kabari semua yang mendaftar saat sesuatu terjadi". Di browser bentuknya button.addEventListener("click", fn), di Node.js bentuknya emitter.on("data", fn). Kodenya beda, polanya sama.
Karena punya nama, pattern juga jadi bahasa tim. Bilang "status paket pakai Observer" lebih cepat daripada menjelaskan daftar fungsi yang dipanggil satu per satu.
Tiga kelompok pattern
Buku Design Patterns (1994) karya empat penulis yang dijuluki Gang of Four mengumpulkan 23 pattern dan membaginya jadi tiga kelompok menurut masalahnya:
| Kelompok | Masalahnya | Contoh pattern | Rasa sakit di Kurir Kancil |
|---|---|---|---|
| Creational | cara object dibuat | Factory, Singleton, Builder | layanan baru harus ditambah di price dan eta |
| Structural | cara object disusun dan disambung | Adapter, Decorator, Facade | data kurir mitra memakai nama field lain |
| Behavioral | cara object saling berkabar dan berbagi kerja | Observer, Strategy, Command | updateStatus diubah tiap ada pihak baru |
Contoh creational dari tebakan tadi:
console.log("sameday:", price("sameday", 2), "rupiah,", eta("sameday"))
// sameday: 50000 rupiah, undefined
price sudah tahu sameday, eta belum, jadi eta("sameday") jatuh ke ujung fungsi tanpa return dan hasilnya undefined. Itu jawaban tebakannya. Gak ada error, cuma data yang bolong. Factory Pattern menyembuhkannya dengan menaruh semua yang perlu diketahui tentang satu layanan di satu tempat:
const SERVICES = {
reguler: { perKg: 10000, eta: "3 hari" },
kilat: { perKg: 18000, eta: "1 hari" },
sameday: { perKg: 25000, eta: "hari ini" }, // layanan baru: satu baris
}
function createShipment(service, kg) {
const s = SERVICES[service]
return { service, price: kg * s.perKg, eta: s.eta }
}
const p = createShipment("sameday", 2)
console.log("sameday:", p.price, "rupiah,", p.eta) // sameday: 50000 rupiah, hari ini
SERVICESmenyimpan tarif dan estimasi tiap layanan berdampingan, jadi gak mungkin yang satu ditambah dan yang lain lupa.createShipmentadalah satu-satunya tempat yang tahu cara membuat object kiriman. Pemanggilnya cukup bilang layanan dan beratnya.
Di track ini juga ada Module Pattern, cara paling dasar menyembunyikan data di JavaScript. Dia gak masuk tiga kelompok di atas karena gak ada di buku itu, tapi di JavaScript dia fondasi buat pattern lainnya.
Mulai dari masalahnya
Pattern itu obat, jadi pakai saat sakitnya ada. Kalau Kurir Kancil cuma punya satu layanan dan belum ada rencana menambah, createShipment dan SERVICES cuma menambah satu nama dan satu lompatan saat membaca kode, tanpa menyembuhkan apa-apa. Tulis versi sederhana dulu. Begitu perubahan yang sama mulai terasa berulang (layanan kedua, ketiga), baru ubah ke pattern yang cocok.
Urutannya selalu sama: sebut masalahnya dulu ("layanan baru harus diubah di dua tempat"), baru cari pattern yang menyelesaikan masalah itu.
⚠️ Jebakan yang sering ketemu
- Pattern dipaksakan. Kode lima baris dibungkus factory, class, dan interface sampai jadi lima puluh baris. Kalau gak ada masalah yang hilang, pattern-nya cuma beban.
- Hafal nama, lupa masalahnya. Tahu definisi Singleton tapi gak bisa bilang kapan dia merugikan sama saja belum paham. Selalu tanya: rasa sakit apa yang hilang?
- Menyalin versi Java ke JavaScript mentah-mentah. Banyak pattern di buku 1994 itu ditulis untuk bahasa yang semuanya harus class. Di JavaScript, sering cukup function, object, atau module. Contohnya Singleton: module JavaScript sudah cuma dijalankan sekali.
- Menganggap pattern sebagai kode siap tempel. Pattern itu bentuk, kodenya kamu tulis sendiri sesuai project.
TL;DR: Design pattern adalah solusi umum yang bisa dipakai ulang untuk masalah desain yang sering muncul. Dia pola, bukan potongan kode: punya nama, masalah, bentuk solusi, dan harga. Tiga kelompoknya: Creational (cara object dibuat: Factory, Singleton, Builder), Structural (cara object disusun: Adapter, Decorator, Facade), Behavioral (cara object berkabar: Observer, Strategy, Command). Contoh sepanjang track ini adalah Kurir Kancil, jasa kirim paket. Mulai dari masalahnya, bukan dari pattern-nya: kalau gak ada rasa sakit yang hilang, jangan pakai pattern.