Pola State
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 95 dari 107.
State pattern memungkinkan sebuah object mengubah perilakunya saat state internalnya berubah, sehingga tampak seolah-olah object tersebut mengubah class-nya. Template Method mengendalikan langkah-langkah algoritma, sedangkan State mengenkapsulasi perilaku khusus untuk setiap state ke dalam object terpisah dan mendelegasikan tugas ke state saat ini.
Di Go, kita mendefinisikan interface state dan membuat state konkret yang menerapkan perilaku berbeda:
type State interface {
Handle(d *Document) string
}
type Document struct {
state State
}
func (d *Document) SetState(s State) {
d.state = s
}
func (d *Document) Publish() string {
return d.state.Handle(d)
}Setiap state menentukan hal yang terjadi dan state berikutnya:
type DraftState struct{}
func (s DraftState) Handle(d *Document) string {
d.SetState(ModerationState{})
return "Draft submitted for moderation"
}
type ModerationState struct{}
func (s ModerationState) Handle(d *Document) string {
d.SetState(PublishedState{})
return "Moderation approved, now published"
}
type PublishedState struct{}
func (s PublishedState) Handle(d *Document) string {
return "Already published"
}Pemanggilan method yang sama menghasilkan nilai yang berbeda berdasarkan state saat ini:
doc := &Document{state: DraftState{}}
fmt.Println(doc.Publish()) // Draf dikirim untuk ditinjau
fmt.Println(doc.Publish()) // Peninjauan disetujui, sekarang diterbitkan
fmt.Println(doc.Publish()) // Sudah diterbitkanState ideal untuk object dengan mode operasi yang berbeda, seperti alur kerja pemrosesan pesanan, komponen UI, atau handler koneksi yang perilakunya sepenuhnya bergantung pada state saat ini.
Tantangan
MudahMari buat sistem dukungan tiket menggunakan pola State! Kamu akan membuat tiket dukungan yang melewati berbagai tahap, mulai dari dibuka, dikerjakan, hingga diselesaikan. Setiap state menentukan tindakan yang mungkin dilakukan dan apa yang terjadi selanjutnya.
Kamu akan mengatur kodemu dalam tiga file:
state.go: Definisikan interface state dan state konkret yang mewakili setiap tahap dalam siklus hidup tiket.Buat interface
TicketStatedengan methodHandle(t *Ticket) stringyang memproses tiket dan mungkin mengalihkannya ke state berikutnya.Implementasikan tiga state:
OpenState: saat ditangani, mengalihkan tiket keInProgressStatedan mengembalikanTicket opened, assigning to support teamInProgressState: saat ditangani, mengalihkan tiket keResolvedStatedan mengembalikanWorking on ticket, issue resolvedResolvedState: saat ditangani, tetap berada di state yang sama dan mengembalikanTicket already resolved
ticket.go: Buat struct tiket yang menyimpan state saat ini dan mendelegasikan perilaku kepadanya.Buat struct
Ticketdengan fieldID(string) dan fieldstate(TicketState). Tambahkan method berikut:SetState(s TicketState)untuk mengubah state tiket saat iniProcess() stringyang mendelegasikan pemrosesan ke method Handle dari state saat ini
Buat konstruktor
NewTicket(id string) *Ticketyang mengembalikan tiket dengan state awalOpenState.main.go: Tunjukkan bagaimana tindakan yang sama menghasilkan keluaran berbeda berdasarkan state tiket saat ini.Baca ID tiket dan berapa kali tiket akan diproses. Buat tiket baru dengan ID tersebut, lalu panggil
Process()sebanyak yang ditentukan dan cetak setiap hasil pada baris terpisah.
Input berikut akan diberikan:
- Baris 1: ID tiket
- Baris 2: Berapa kali tiket diproses
Contohnya, jika diberikan:
TKT-001
3Output-mu seharusnya:
Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolvedDan jika diberikan:
TKT-500
5Output-mu seharusnya:
Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved
Ticket already resolved
Ticket already resolvedDan jika diberikan:
ISSUE-42
1Output-mu seharusnya:
Ticket opened, assigning to support teamPerhatikan bagaimana pemanggilan Process() pada tiket yang sama menghasilkan keluaran berbeda setiap kali: perilaku tiket berubah saat berpindah melalui berbagai state. Setelah diselesaikan, tiket tetap berstatus selesai, berapa kali pun kamu memprosesnya. Object tiket tampak mengubah perilakunya, tetapi sebenarnya object tersebut mendelegasikan pemrosesan ke berbagai object state!
Coba sendiri
package main
import (
"fmt"
)
func main() {
// Baca input
var ticketID string
var numProcesses int
fmt.Scanln(&ticketID)
fmt.Scanln(&numProcesses)
// TODO: Buat tiket baru dengan ID yang diberikan
// TODO: Proses tiket sebanyak jumlah yang ditentukan
// dan cetak setiap hasil pada baris terpisah
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File11Pustaka Standar & OOP
io.Reader & io.Writersort.InterfaceAntarmuka fmt.Stringerencoding/json dengan StructAntarmuka http.HandlerRingkasan, Model REST API14Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositeMiddleware sebagai Decorator3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online