Pola desain adalah templat yang memecahkan masalah yang sering muncul kembali dalam desain perangkat lunak.
Pola keadaan adalah pola perilaku yang memungkinkan suatu objek mengubah perilakunya ketika keadaan internalnya berubah.
Di sini Anda akan belajar cara menggunakan pola status di TypeScript.
Bagaimana Pola Negara?
Pola desain negara terkait erat dengan mesin negara-hingga, yang menggambarkan program yang ada di a terbatas jumlah negara pada saat tertentu dan berperilaku berbeda dalam setiap negara.
Ada aturan terbatas yang telah ditentukan sebelumnya—transisi—yang mengatur negara bagian lain yang dapat dialihkan ke setiap negara bagian.
Untuk konteksnya, di toko online, jika pesanan belanja pelanggan sudah “diantar”, tidak bisa “dibatalkan” karena sudah “diantar”. "Terkirim" dan "Dibatalkan" adalah status pesanan yang terbatas, dan pesanan akan berperilaku berbeda berdasarkan statusnya.
Pola negara menciptakan sebuah kelas untuk setiap status yang mungkin, dengan perilaku khusus negara bagian yang terkandung di setiap kelas.
Contoh Aplikasi Berbasis Negara
Misalnya, asumsikan Anda membuat aplikasi yang melacak status artikel untuk perusahaan penerbitan. Sebuah artikel dapat menunggu persetujuan, disusun oleh penulis, diedit oleh editor, atau diterbitkan. Ini adalah keadaan terbatas dari sebuah artikel yang akan diterbitkan; dalam setiap keadaan unik, artikel berperilaku berbeda.
Anda dapat memvisualisasikan status dan transisi yang berbeda dari aplikasi artikel dengan diagram status di bawah ini:
Menerapkan skenario ini dalam kode, pertama-tama Anda harus mendeklarasikan antarmuka untuk Artikel:
antarmukaArtikelAntarmuka{
melempar(): ruang kosong;
draf(): ruang kosong;
sunting(): ruang kosong;
menerbitkan(): ruang kosong;
}
Antarmuka ini akan memiliki semua kemungkinan status aplikasi.
Selanjutnya, buat aplikasi yang mengimplementasikan semua metode antarmuka:
// Aplikasi
kelasArtikelalatArtikelAntarmuka{
konstruktor() {
ini.showCurrentState();
}pribadishowCurrentState(): ruang kosong{
//...
}publikmelempar(): ruang kosong{
//...
}publikdraf(): ruang kosong{
//...
}publiksunting(): ruang kosong{
//...
}
publikmenerbitkan(): ruang kosong{
//...
}
}
Pribadi showCurrentState metode adalah metode utilitas. Tutorial ini menggunakannya untuk menunjukkan apa yang terjadi di setiap negara bagian. Ini bukan bagian wajib dari pola negara.
Menangani Transisi Status
Selanjutnya, Anda harus menangani transisi status. Menangani transisi status di kelas aplikasi Anda akan membutuhkan banyak hal pernyataan bersyarat. Ini akan menghasilkan kode berulang yang lebih sulit dibaca dan dipelihara. Untuk mengatasi masalah ini, Anda dapat mendelegasikan logika transisi untuk setiap status ke kelasnya sendiri.
Sebelum Anda menulis setiap kelas status, Anda harus membuat kelas dasar abstrak untuk memastikan metode apa pun yang dipanggil dalam status tidak valid menghasilkan kesalahan.
Misalnya:
abstrakkelasArtikelStatealatArtikelAntarmuka{
lapangan(): ArticleState {
melemparkanbaruKesalahan("Operasi Tidak Valid: Tidak dapat melakukan tugas di dalam kondisi saat ini");
}draft(): ArticleState {
melemparkanbaruKesalahan("Operasi Tidak Valid: Tidak dapat melakukan tugas di dalam kondisi saat ini");
}edit(): ArticleState {
melemparkanbaruKesalahan("Operasi Tidak Valid: Tidak dapat melakukan tugas di dalam kondisi saat ini");
}
terbitkan(): ArticleState {
melemparkanbaruKesalahan("Operasi Tidak Valid: Tidak dapat melakukan tugas di dalam kondisi saat ini");
}
}
Di kelas dasar di atas, setiap metode melempar kesalahan. Sekarang, Anda harus mengganti setiap metode dengan membuat kelas khusus yang memanjang kelas dasar untuk setiap negara bagian. Setiap kelas tertentu akan berisi logika khusus negara bagian.
Setiap aplikasi memiliki keadaan diam, yang menginisialisasi aplikasi. Status siaga untuk aplikasi ini akan menyetel aplikasi ke draf negara.
Misalnya:
kelasPendingDraftStatememanjangArtikelState{
lapangan(): ArticleState {
kembalibaru DraftState();
}
}
Itu melempar metode di kelas di atas menginisialisasi aplikasi dengan menyetel status saat ini ke DraftState.
Selanjutnya, timpa metode lainnya seperti ini:
kelasDraftStatememanjangArtikelState{
draft(): ArticleState {
kembalibaru EditingState();
}
}
Kode ini menimpa draf metode dan mengembalikan sebuah instance dari EditingState.
kelasEditingStatememanjangArtikelState{
edit(): ArticleState {
kembalibaru PublishedState();
}
}
Blok kode di atas menimpa sunting metode dan mengembalikan sebuah instance dari PublishedState.
kelasPublishedStatememanjangArtikelState{
terbitkan(): ArticleState {
kembalibaru PendingDraftState();
}
}
Blok kode di atas menimpa menerbitkan metode dan mengembalikan aplikasi ke keadaan diam, PendingDraftState.
Kemudian, Anda harus mengizinkan aplikasi mengubah statusnya secara internal dengan mereferensikan status saat ini melalui variabel pribadi. Anda dapat melakukan ini dengan menginisialisasi status diam di dalam kelas aplikasi Anda dan menyimpan nilainya ke variabel privat:
pribadi status: ArticleState = baru PendingDraftState();
Selanjutnya, perbarui showCurrentState metode untuk mencetak nilai status saat ini:
pribadishowCurrentState(): ruang kosong{
menghibur.catatan(ini.negara);
}
Itu showCurrentState method mencatat status aplikasi saat ini ke konsol.
Terakhir, tetapkan kembali variabel privat ke instance status saat ini di setiap metode aplikasi Anda.
Misalnya, perbarui aplikasi Anda melempar metode ke blok kode di bawah ini:
publikmelempar(): ruang kosong{
ini.keadaan = ini.state.pitch();
ini.showCurrentState();
}
Di blok kode di atas, file melempar metode mengubah keadaan dari keadaan saat ini ke keadaan lapangan.
Demikian pula, semua metode lain akan mengubah status dari status aplikasi saat ini ke statusnya masing-masing.
Perbarui metode aplikasi Anda ke blok kode di bawah ini:
Itu draf metode:
publikdraf(): ruang kosong{
ini.keadaan = ini.negara.draft();
ini.showCurrentState();
}
Itu sunting metode:
publiksunting(): ruang kosong{
ini.keadaan = ini.negara.edit();
ini.showCurrentState();
}
Dan menerbitkan metode:
publikmenerbitkan(): ruang kosong{
ini.keadaan = ini.state.publish();
ini.showCurrentState();
}
Menggunakan Aplikasi Selesai
Kelas aplikasi Anda yang sudah selesai harus serupa dengan blok kode di bawah ini:
// Aplikasi
kelasArtikelalatArtikelAntarmuka{
pribadi status: ArticleState = baru PendingDraftState();konstruktor() {
ini.showCurrentState();
}pribadishowCurrentState(): ruang kosong{
menghibur.catatan(ini.negara);
}publikmelempar(): ruang kosong{
ini.keadaan = ini.state.pitch();
ini.showCurrentState();
}publikdraf(): ruang kosong{
ini.keadaan = ini.negara.draft();
ini.showCurrentState();
}publiksunting(): ruang kosong{
ini.keadaan = ini.negara.edit();
ini.showCurrentState();
}
publikmenerbitkan(): ruang kosong{
ini.keadaan = ini.state.publish();
ini.showCurrentState();
}
}
Anda dapat menguji transisi status dengan memanggil metode dalam urutan yang benar. Misalnya:
const dokumen = baru Artikel(); // PendingDraftState: {}
docs.pitch(); // Status Draf: {}
docs.draft(); // Status Pengeditan: {}
docs.edit(); // Status Terbit: {}
docs.publish(); // PendingDraftState: {}
Blok kode di atas berfungsi karena status aplikasi ditransisikan dengan tepat.
Jika Anda mencoba mengubah status dengan cara yang tidak diperbolehkan, misalnya, dari status pitch ke status edit, aplikasi akan menampilkan kesalahan:
const dokumen = baru Artikel(); // PendingDraftState: {}
docs.pitch() // Status Draf: {}
docs.edit() // Operasi Tidak Valid: Tidak dapat melakukan tugas dalam kondisi saat ini
Anda sebaiknya hanya menggunakan pola ini saat:
- Anda membuat objek yang berperilaku berbeda bergantung pada statusnya saat ini.
- Objek memiliki banyak status.
- Perilaku spesifik negara sering berubah.
Keuntungan dan Trade-Off dari Pola Negara
Pola ini menghilangkan pernyataan bersyarat yang besar dan mempertahankan tanggung jawab tunggal dan prinsip terbuka/tertutup. Tapi itu bisa berlebihan jika aplikasi memiliki sedikit status atau statusnya tidak terlalu dinamis.