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] HELLODecorator 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.
Tantangan
MudahMari 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
Beveragedengan dua method:Description() string: mengembalikan deskripsi minumanCost() float64: mengembalikan harga
Implementasikan struct
Coffeesebagai minuman dasar. Deskripsinya harus berupaCoffeedan harganya harus2.00.decorators.go: Buat tipe decorator yang menambahkan ekstra ke minuman apa pun.Setiap decorator membungkus
Beveragedan mengimplementasikan interface yang sama. Buat tiga decorator:MilkDecorator: menambahkan, Milkke deskripsi dan0.50ke hargaSugarDecorator: menambahkan, Sugarke deskripsi dan0.25ke hargaWhipDecorator: menambahkan, Whipke deskripsi dan0.75ke 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, atauwhip) 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.XXdengan 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, atauwhip)
Contohnya, jika diberikan:
2
milk
sugarOutput kamu seharusnya:
Coffee, Milk, Sugar
$2.75Dan jika diberikan:
3
whip
milk
milkOutput kamu seharusnya:
Coffee, Whip, Milk, Milk
$3.75Dan jika diberikan:
0Output kamu seharusnya:
Coffee
$2.00Perhatikan 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
}
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