Menu
CoddyTech

Pola Decorator

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

Pola Decorator memungkinkan kamu menambahkan perilaku baru ke object secara dinamis dengan membungkusnya dalam object lain. Adapter mengubah antarmuka agar sesuai dengan antarmuka lain, sedangkan Decorator mempertahankan antarmuka yang sama, tetapi meningkatkan fungsionalitas dengan menambahkan lapisan pembungkus di sekitar object asli.

Di Go, kita menerapkan ini dengan membuat tipe dasar dan dekorator sama-sama menerapkan interface yang sama:

type Notifier interface {
    Send(message string) string
}

type BasicNotifier struct{}

func (b BasicNotifier) Send(message string) string {
    return "Sending: " + message
}

Decorator membungkus Notifier lain dan menambahkan perilaku sebelum atau sesudah meneruskan pemanggilan kepadanya:

type TimestampDecorator struct {
    wrapped Notifier
}

func (t TimestampDecorator) Send(message string) string {
    timestamped := "[2024-01-15] " + message
    return t.wrapped.Send(timestamped)
}

type UppercaseDecorator struct {
    wrapped Notifier
}

func (u UppercaseDecorator) Send(message string) string {
    return strings.ToUpper(u.wrapped.Send(message))
}

Kekuatan Decorator terletak pada penumpukan beberapa wrapper untuk menggabungkan perilaku:

notifier := BasicNotifier{}
withTimestamp := TimestampDecorator{wrapped: notifier}
withBoth := UppercaseDecorator{wrapped: withTimestamp}

fmt.Println(notifier.Send("Hello"))
// Mengirim: Hello

fmt.Println(withBoth.Send("Hello"))
// MENGIRIM: [2024-01-15] HELLO

Decorator ideal digunakan saat kamu perlu menambahkan tanggung jawab ke object tanpa mengubah kodemu, terutama saat diperlukan berbagai kombinasi fitur. Decorator umum digunakan untuk lapisan pencatatan log, caching, autentikasi, dan kompresi.

challenge icon

Tantangan

Mudah

Mari buat sistem pemesanan kedai kopi menggunakan pola Decorator! Kamu akan membuat minuman kopi dasar dan decorator yang menambahkan ekstra seperti susu, gula, dan krim kocok. Setiap decorator membungkus decorator sebelumnya, membentuk deskripsi dan harga: contoh nyata yang sempurna tentang cara decorator menumpuk fungsionalitas.

Kamu akan mengatur kodemu dalam tiga file:

  • beverage.go: Definisikan interface inti dan tipe kopi dasar.

    Buat interface Beverage dengan dua method:

    • Description() string: mengembalikan deskripsi minuman
    • Cost() float64: mengembalikan harga

    Implementasikan struct Coffee sebagai minuman dasar. Deskripsinya harus berupa Coffee dan harganya harus 2.00.

  • decorators.go: Buat tipe decorator yang menambahkan ekstra ke minuman apa pun.

    Setiap decorator membungkus Beverage dan mengimplementasikan interface yang sama. Buat tiga decorator:

    • MilkDecorator: menambahkan , Milk ke deskripsi dan 0.50 ke harga
    • SugarDecorator: menambahkan , Sugar ke deskripsi dan 0.25 ke harga
    • WhipDecorator: menambahkan , Whip ke deskripsi dan 0.75 ke harga

    Setiap decorator harus memanggil method minuman yang dibungkusnya dan menyempurnakan hasilnya.

  • main.go: Buat minuman sesuai pilihan dengan menumpuk decorator.

    Baca jumlah ekstra yang akan ditambahkan. Lalu, untuk setiap ekstra, baca jenisnya (milk, sugar, atau whip) dan bungkus minuman saat ini dengan decorator yang sesuai.

    Setelah menerapkan semua ekstra, cetak deskripsi dan harga akhir minuman pada baris terpisah. Format harga sebagai $X.XX dengan tepat dua angka di belakang titik desimal.

Input berikut akan diberikan:

  • Baris 1: Jumlah ekstra yang akan ditambahkan
  • Baris berikutnya: Satu jenis ekstra per baris (milk, sugar, atau whip)

Contohnya, jika diberikan:

2
milk
sugar

Output kamu seharusnya:

Coffee, Milk, Sugar
$2.75

Dan jika diberikan:

3
whip
milk
milk

Output kamu seharusnya:

Coffee, Whip, Milk, Milk
$3.75

Dan jika diberikan:

0

Output kamu seharusnya:

Coffee
$2.00

Perhatikan bahwa setiap decorator membungkus minuman sebelumnya, membentuk deskripsi dan harga. Kamu dapat menambahkan ekstra yang sama beberapa kali, seperti susu ganda, dan urutan decorator menentukan urutan dalam deskripsi. Kopi dasar tidak mengetahui apa pun tentang ekstra: setiap decorator hanya menyempurnakan apa pun yang dibungkusnya!

Coba sendiri

package main

import (
	"fmt"
)

func main() {
	// Baca jumlah tambahan
	var count int
	fmt.Scanln(&count)

	// Mulai dengan kopi dasar
	var drink Beverage = &Coffee{}

	// Baca setiap tambahan dan bungkus minuman dengan dekorator yang sesuai
	for i := 0; i < count; i++ {
		var extra string
		fmt.Scanln(&extra)

		// TODO: Berdasarkan jenis tambahan, bungkus drink dengan dekorator yang sesuai
		// Gunakan MilkDecorator untuk "milk"
		// Gunakan SugarDecorator untuk "sugar"
		// Gunakan WhipDecorator untuk "whip"
	}

	// TODO: Cetak deskripsi akhir dan biaya
	// Format biaya sebagai $X.XX dengan tepat dua angka di belakang koma
}
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