Pemrograman · Pola desain
Pola Facade dijelaskan dengan contoh
Jawaban singkat
Facade adalah pola desain structural yang menyediakan satu interface sederhana dan tingkat lebih tinggi untuk sekumpulan interface dalam subsistem yang kompleks. Alih-alih memanggil layanan inventaris, pembayaran, pengiriman, dan email dalam urutan yang benar, kode klien memanggil satu method seperti shop.placeOrder(), dan facade mengoordinasikan kelas-kelas subsistem. Subsistem tetap ada dan dapat dipakai langsung bila perlu; facade hanya membuat kasus yang umum menjadi mudah.
Tujuan
Menyediakan interface terpadu untuk sekumpulan interface dalam subsistem. Facade mendefinisikan interface tingkat lebih tinggi yang membuat subsistem lebih mudah dipakai. Pola ini salah satu dari tujuh pola structural dalam buku Gang of Four (GoF).
Masalah yang diselesaikan
Bayangkan toko online. Menempatkan pesanan membutuhkan beberapa layanan: memeriksa dan mencadangkan stok, menagih kartu, melepas stok jika pembayaran gagal, membuat pengiriman, dan mengirim email konfirmasi. Setiap layanan punya API dan aturannya sendiri.
Jika setiap pemanggil, seperti checkout web, API mobile, dan alat admin, menjalankan langkah-langkah ini sendiri, urutan yang sama disalin di banyak tempat. Setiap salinan bisa salah urutan atau lupa rollback, dan setiap pemanggil bergantung pada lima layanan. Ketika satu layanan berubah, semua pemanggil harus berubah. Facade menaruh urutan itu di satu tempat dan memberi pemanggil satu method.
Struktur dan peserta
| Peserta | Tanggung jawab | Dalam contoh |
|---|---|---|
| Facade | Mengetahui kelas subsistem mana yang menangani suatu permintaan dan mendelegasikan kepada mereka dalam urutan yang benar. | OrderFacade |
| Kelas subsistem | Mengerjakan pekerjaan sebenarnya. Mereka tidak tahu tentang facade. | Inventory, Payments, Shipping, Mailer |
| Klien | Memakai facade untuk tugas umum; masih boleh memakai kelas subsistem secara langsung untuk kasus khusus. | kode checkout |
Implementasi TypeScript
// Subsystem classes, each with its own API.
class Inventory {
private stock = new Map([["book", 2]]);
reserve(sku: string): boolean {
const n = this.stock.get(sku) ?? 0;
if (n === 0) return false;
this.stock.set(sku, n - 1);
return true;
}
release(sku: string): void { this.stock.set(sku, (this.stock.get(sku) ?? 0) + 1); }
}
class Payments {
charge(card: string, cents: number): boolean { return card.startsWith("4") && cents > 0; }
}
class Shipping {
createShipment(sku: string, address: string): string { return `SHIP-${sku}-${address.length}`; }
}
class Mailer {
send(to: string, text: string): void { console.log(`mail to ${to}: ${text}`); }
}Facade lalu menjalankan seluruh alur kerja dalam urutan yang benar di balik satu method:
// Facade: one method that runs the whole workflow in the right order.
class OrderFacade {
constructor(private inventory = new Inventory(), private payments = new Payments(),
private shipping = new Shipping(), private mailer = new Mailer()) {}
placeOrder(sku: string, card: string, cents: number, email: string, address: string): string {
if (!this.inventory.reserve(sku)) return "out of stock";
if (!this.payments.charge(card, cents)) {
this.inventory.release(sku); // roll back the reservation
return "payment declined";
}
const shipmentId = this.shipping.createShipment(sku, address);
this.mailer.send(email, `Order confirmed, shipment ${shipmentId}`);
return "ok";
}
}
const shop = new OrderFacade();
console.log(shop.placeOrder("book", "4111", 1999, "[email protected]", "1 Main St"));
// mail to [email protected]: Order confirmed, shipment SHIP-book-9
// ok
console.log(shop.placeOrder("book", "5500", 1999, "[email protected]", "2 Side St")); // payment declinedPemanggil sekarang bergantung pada satu kelas dengan satu method. Aturan rollback hanya ada satu kali. Kelas subsistem tetap tersedia, sehingga alat admin yang hanya perlu melepas stok dapat memanggil Inventory secara langsung.
Kapan memakainya, dan kapan tidak
Gunakan pola Facade ketika:
- Subsistem kompleks dan sebagian besar klien hanya membutuhkan subset umum yang sederhana dari kemampuannya.
- Anda ingin mengurangi jumlah dependensi antara kode klien dan banyak kelas subsistem.
- Anda ingin mengorganisasi sistem ke dalam lapisan, dengan facade sebagai pintu masuk setiap lapisan.
- Anda membungkus pustaka pihak ketiga yang besar dan ingin sisa kode Anda hanya memakai beberapa operasi yang dibutuhkan.
Hindari atau batasi ketika:
- Subsistem sudah sederhana. Facade yang meneruskan tiap panggilan satu lawan satu menambah lapisan tanpa menyembunyikan apa pun.
- Facade mulai mengumpulkan method yang tidak berhubungan dan aturan bisnis dari seluruh sistem. Ini masalah "god object": satu kelas yang tahu dan mengerjakan terlalu banyak. Pecah menjadi beberapa facade yang terfokus.
Pemakaian di dunia nyata
- Node.js:
fs.readFile()membuka file, membacanya sampai akhir, dan menutupnya dalam satu panggilan.fs.open(),fs.read(), danfs.close()yang lebih rendah tetap tersedia. - jQuery populer sebagian besar karena menaruh satu API yang singkat dan konsisten di depan DOM dan perbedaan browser pada masanya.
- Contoh dalam buku GoF adalah compiler: satu kelas
Compilermenyembunyikan scanner, parser, code generator, dan kelas subsistem lain dari program yang hanya ingin mengompilasi kode. - Service layer dan API gateway di aplikasi back-end bertindak sebagai facade di atas banyak layanan internal.
Pola terkait
| Pola | Perbedaannya dengan Facade |
|---|---|
| Adapter | Membuat satu interface yang ada cocok dengan interface lain yang ada. Facade mendefinisikan interface baru yang lebih sederhana untuk banyak kelas. |
| Mediator | Juga memusatkan koordinasi, tetapi objek subsistem mengenal mediator dan berkomunikasi lewat mediator. Dengan facade, kelas subsistem tidak tahu bahwa facade ada. |
| Abstract Factory | Dapat dipakai bersama facade untuk membuat objek subsistem secara independen dari platform. |
| Singleton | Facade sering berupa instance tunggal, karena satu pintu masuk ke subsistem biasanya sudah cukup. |
| Proxy | Memiliki interface yang sama dengan satu objek dan mengontrol akses ke objek itu. Facade memiliki interface berbeda yang lebih sederhana di atas banyak objek. |
FAQ
Apa beda pola Facade dan pola Adapter?
Adapter mengubah satu interface yang ada menjadi interface lain yang sudah diharapkan klien. Facade menciptakan interface baru yang lebih sederhana agar seluruh subsistem lebih mudah dipakai.
Apakah facade menyembunyikan subsistem sepenuhnya?
Tidak. Facade membuat tugas umum menjadi mudah, tetapi klien yang membutuhkan kendali lebih tetap dapat memakai kelas subsistem secara langsung.
Bisakah satu sistem punya lebih dari satu facade?
Bisa. Sistem besar sering punya satu facade per subsistem atau per kasus penggunaan, sehingga setiap facade tetap kecil dan terfokus.
Apakah service layer itu facade?
Sering kali ya. Method service yang mengoordinasikan repository, API eksternal, dan notifikasi di balik satu panggilan berperan sebagai facade bagi kode yang memanggilnya.