Menu
CoddyTech

Pola Command

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 91 dari 107.

Pola Command membungkus permintaan sebagai object, sehingga kamu dapat memparameterkan operasi, mengantrekannya, atau mendukung fungsi undo. Strategy membungkus algoritma, sedangkan Command membungkus seluruh tindakan beserta parameternya.

Di Go, kita mendefinisikan antarmuka Command dengan method Execute, lalu membuat perintah konkret yang menyimpan semua informasi yang diperlukan untuk melakukan suatu tindakan:

type Command interface {
    Execute() string
}

type Light struct {
    IsOn bool
}

type TurnOnCommand struct {
    light *Light
}

func (c *TurnOnCommand) Execute() string {
    c.light.IsOn = true
    return "Light turned on"
}

type TurnOffCommand struct {
    light *Light
}

func (c *TurnOffCommand) Execute() string {
    c.light.IsOn = false
    return "Light turned off"
}

Invoker menyimpan dan menjalankan perintah tanpa mengetahui apa yang dilakukan perintah tersebut:

type RemoteControl struct {
    command Command
}

func (r *RemoteControl) SetCommand(c Command) {
    r.command = c
}

func (r *RemoteControl) PressButton() string {
    return r.command.Execute()
}

Invoker sepenuhnya terpisah dari penerima (Light):

light := &Light{}
remote := &RemoteControl{}

remote.SetCommand(&TurnOnCommand{light: light})
fmt.Println(remote.PressButton())  // Lampu menyala

remote.SetCommand(&TurnOffCommand{light: light})
fmt.Println(remote.PressButton())  // Lampu mati

Command ideal untuk menerapkan sistem undo/redo, antrean tugas, atau perekaman makro saat kamu perlu menyimpan, menunda, atau memutar ulang operasi.

challenge icon

Tantangan

Mudah

Mari buat editor teks dengan fungsi undo menggunakan pola Command! Kamu akan membuat perintah yang merangkum operasi teks, sehingga editor dapat menjalankan tindakan dan membatalkannya: contoh klasik yang menunjukkan mengapa perintah sangat berguna.

Kamu akan mengatur kodemu dalam tiga file:

  • command.go: Definisikan interface perintah dan perintah pengeditan teks konkret.

    Buat interface Command dengan dua method: Execute() string untuk melakukan tindakan dan Undo() string untuk membatalkannya.

    Implementasikan dua tipe perintah yang beroperasi pada *TextEditor:

    • InsertCommand: menyimpan pointer editor dan teks yang akan disisipkan. Execute menambahkan teks ke konten editor dan mengembalikan Inserted: [text]. Undo menghapus teks itu dari akhir dan mengembalikan Undone insert: [text]
    • DeleteCommand: menyimpan pointer editor dan jumlah karakter yang akan dihapus dari akhir. Execute menghapus karakter tersebut (dan menyimpannya untuk undo) lalu mengembalikan Deleted: [removed text]. Undo memulihkannya dan mengembalikan Undone delete: [restored text]
  • editor.go: Buat editor teksmu (receiver) dan invoker yang mengelola riwayat perintah.

    Buat struct TextEditor dengan field Content (string) dan method Append(text string) serta DeleteLast(count int) string (mengembalikan teks yang dihapus).

    Buat struct EditorInvoker yang menyimpan slice perintah yang telah dijalankan sebagai riwayat. Tambahkan method berikut:

    • ExecuteCommand(cmd Command) string: menjalankan perintah, menambahkannya ke riwayat, dan mengembalikan hasilnya
    • UndoLast() string: menghapus perintah terakhir dari riwayat, memanggil Undo, dan mengembalikan hasilnya. Jika riwayat kosong, kembalikan Nothing to undo
  • main.go: Peragakan sistem perintahmu dengan serangkaian operasi.

    Baca jumlah operasi. Untuk setiap operasi, baca tipe operasinya (insert, delete, atau undo). Untuk insert, baca juga teks yang akan disisipkan. Untuk delete, baca jumlah karakter. Jalankan setiap operasi melalui invoker-mu dan cetak hasilnya. Setelah semua operasi, cetak konten akhir editor sebagai Final: [content].

Input berikut akan diberikan:

  • Baris 1: Jumlah operasi
  • Untuk setiap operasi: tipe operasi, lalu data tambahan jika diperlukan (teks untuk insert, jumlah karakter untuk delete)

Contohnya, jika diberikan:

5
insert
Hello
insert
 World
delete
3
undo
undo

Outputmu seharusnya:

Inserted: Hello
Inserted:  World
Deleted: rld
Undone delete: rld
Undone insert:  World
Final: Hello

Dan jika diberikan:

4
insert
Go
insert
Lang
undo
insert
!

Outputmu seharusnya:

Inserted: Go
Inserted: Lang
Undone insert: Lang
Inserted: !
Final: Go!

Dan jika diberikan:

2
undo
insert
Test

Outputmu seharusnya:

Nothing to undo
Inserted: Test
Final: Test

Perhatikan bagaimana setiap perintah merangkum semua yang diperlukan untuk melakukan dan membatalkan tindakannya. Invoker tidak mengetahui apa yang dilakukan perintah-perintah tersebut. Invoker hanya menjalankannya dan mengelola riwayat untuk mendukung undo!

Coba sendiri

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Baca jumlah operasi
	line, _ := reader.ReadString('\n')
	numOps, _ := strconv.Atoi(strings.TrimSpace(line))
	
	// Buat editor dan invoker
	editor := &TextEditor{}
	invoker := &EditorInvoker{}
	
	for i := 0; i < numOps; i++ {
		// Baca jenis operasi
		opLine, _ := reader.ReadString('\n')
		opType := strings.TrimSpace(opLine)
		
		var result string
		
		switch opType {
		case "insert":
			// Baca teks yang akan disisipkan
			textLine, _ := reader.ReadString('\n')
			text := strings.TrimSuffix(textLine, "\n")
			
			// TODO: Buat InsertCommand dan jalankan melalui invoker
			_ = text
			_ = editor
			
		case "delete":
			// Baca jumlah karakter yang akan dihapus
			countLine, _ := reader.ReadString('\n')
			count, _ := strconv.Atoi(strings.TrimSpace(countLine))
			
			// TODO: Buat DeleteCommand dan jalankan melalui invoker
			_ = count
			
		case "undo":
			// TODO: Panggil UndoLast pada invoker
			
		}
		
		fmt.Println(result)
	}
	
	// Cetak isi akhir
	fmt.Printf("Final: %s\n", editor.Content)
}
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