Menu
CoddyTech

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 diterbitkan

State 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.

challenge icon

Tantangan

Mudah

Mari 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 TicketState dengan method Handle(t *Ticket) string yang memproses tiket dan mungkin mengalihkannya ke state berikutnya.

    Implementasikan tiga state:

    • OpenState: saat ditangani, mengalihkan tiket ke InProgressState dan mengembalikan Ticket opened, assigning to support team
    • InProgressState: saat ditangani, mengalihkan tiket ke ResolvedState dan mengembalikan Working on ticket, issue resolved
    • ResolvedState: saat ditangani, tetap berada di state yang sama dan mengembalikan Ticket already resolved
  • ticket.go: Buat struct tiket yang menyimpan state saat ini dan mendelegasikan perilaku kepadanya.

    Buat struct Ticket dengan field ID (string) dan field state (TicketState). Tambahkan method berikut:

    • SetState(s TicketState) untuk mengubah state tiket saat ini
    • Process() string yang mendelegasikan pemrosesan ke method Handle dari state saat ini

    Buat konstruktor NewTicket(id string) *Ticket yang mengembalikan tiket dengan state awal OpenState.

  • 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
3

Output-mu seharusnya:

Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved

Dan jika diberikan:

TKT-500
5

Output-mu seharusnya:

Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved
Ticket already resolved
Ticket already resolved

Dan jika diberikan:

ISSUE-42
1

Output-mu seharusnya:

Ticket opened, assigning to support team

Perhatikan 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
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Go online