Pola Builder di Go
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 80 dari 107.
Builder Pattern memisahkan konstruksi object yang kompleks dari representasinya. Berbeda dengan pola Functional Options, Builder menggunakan struct builder khusus dengan method yang mengonfigurasi object langkah demi langkah.
Berikut cara mengimplementasikan builder untuk permintaan HTTP:
type Request struct {
method string
url string
headers map[string]string
body string
}
type RequestBuilder struct {
request *Request
}
func NewRequestBuilder() *RequestBuilder {
return &RequestBuilder{
request: &Request{
headers: make(map[string]string),
},
}
}
func (b *RequestBuilder) Method(m string) *RequestBuilder {
b.request.method = m
return b
}
func (b *RequestBuilder) URL(u string) *RequestBuilder {
b.request.url = u
return b
}
func (b *RequestBuilder) Header(key, value string) *RequestBuilder {
b.request.headers[key] = value
return b
}
func (b *RequestBuilder) Build() *Request {
return b.request
}Setiap method mengembalikan pointer builder, sehingga method dapat dirangkai. Method Build() menyelesaikan proses dan mengembalikan object yang telah dibuat:
req := NewRequestBuilder().
Method("POST").
URL("https://api.example.com").
Header("Content-Type", "application/json").
Build()Pola Builder sangat cocok ketika object memerlukan beberapa langkah konfigurasi atau ketika kamu ingin memastikan urutan pembuatan tertentu. Pola ini sangat berguna untuk membuat object yang immutable atau ketika proses pembuatannya sendiri perlu divalidasi.
Tantangan
MudahMari kita buat penyusun pesan email menggunakan Builder Pattern! Pesan email memiliki banyak komponen opsional, seperti penerima, CC, subjek, isi, dan lampiran, sehingga sangat cocok dibuat langkah demi langkah dengan method chaining.
Kamu akan mengatur kodemu dalam dua file:
email.go: Definisikan struktur email dan builder-nya.Buat struct
Emaildengan field berikut:from(string)to(slice berisi string)cc(slice berisi string)subject(string)body(string)
Buat struct
EmailBuilderyang menyimpan pointer ke Email yang sedang dibuat. ImplementasikanNewEmailBuilder()yang mengembalikan builder baru dengan Email yang telah diinisialisasi (slice kosong untuktodancc).Tambahkan method builder berikut, yang masing-masing mengembalikan
*EmailBuilderagar bisa dirangkai:From(address string)- mengatur pengirimTo(address string)- menambahkan penerima ke slicetoCC(address string)- menambahkan penerima ke sliceccSubject(subject string)- mengatur baris subjekBody(body string)- mengatur isi email
Tambahkan method
Build()yang mengembalikan*Emailyang telah dibuat.Terakhir, tambahkan method
Summary()pada Email yang mengembalikan string dengan format berikut:From: [from] To: [comma-separated to addresses] CC: [comma-separated cc addresses or "none"] Subject: [subject] Body: [body]main.go: Buat dan tampilkan pesan email menggunakan builder.Baca alamat pengirim, lalu baca jumlah penerima dan alamat setiap penerima. Berikutnya, baca jumlah penerima CC dan setiap alamat CC. Terakhir, baca subjek dan isi email.
Gunakan EmailBuilder dengan method chaining untuk membuat email, lalu cetak ringkasannya.
Input berikut akan diberikan:
- Baris 1: Alamat pengirim
- Baris 2: Jumlah penerima
- Baris-baris berikutnya: Alamat setiap penerima
- Baris berikutnya: Jumlah penerima CC
- Baris-baris berikutnya: Setiap alamat CC
- Baris berikutnya: Subjek
- Baris terakhir: Isi email
Contohnya, jika diberikan:
alice@company.com
2
bob@company.com
carol@company.com
1
manager@company.com
Weekly Report
Please find the weekly report attached.Outputmu seharusnya:
From: alice@company.com
To: bob@company.com, carol@company.com
CC: manager@company.com
Subject: Weekly Report
Body: Please find the weekly report attached.Dan jika diberikan:
support@service.com
1
customer@email.com
0
Your Ticket Update
Your support ticket has been resolved.Outputmu seharusnya:
From: support@service.com
To: customer@email.com
CC: none
Subject: Your Ticket Update
Body: Your support ticket has been resolved.Perhatikan bagaimana builder memungkinkanmu menambahkan beberapa penerima satu per satu melalui pemanggilan To() berulang, dan bagaimana pola ini menjaga proses pembuatan tetap rapi dan mudah dibaca meskipun ada banyak field opsional.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Baca alamat pengirim
from, _ := reader.ReadString('\n')
from = strings.TrimSpace(from)
// Baca jumlah penerima
toCountStr, _ := reader.ReadString('\n')
toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))
// Baca alamat setiap penerima
toAddresses := make([]string, toCount)
for i := 0; i < toCount; i++ {
addr, _ := reader.ReadString('\n')
toAddresses[i] = strings.TrimSpace(addr)
}
// Baca jumlah penerima CC
ccCountStr, _ := reader.ReadString('\n')
ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))
// Baca setiap alamat CC
ccAddresses := make([]string, ccCount)
for i := 0; i < ccCount; i++ {
addr, _ := reader.ReadString('\n')
ccAddresses[i] = strings.TrimSpace(addr)
}
// Baca subjek
subject, _ := reader.ReadString('\n')
subject = strings.TrimSpace(subject)
// Baca isi email
body, _ := reader.ReadString('\n')
body = strings.TrimSpace(body)
// TODO: Gunakan EmailBuilder dengan merangkai method untuk membuat email
// Mulai dengan NewEmailBuilder(), lalu rangkai From(), To(), CC(), Subject(), Body()
// Terakhir, panggil Build() untuk mendapatkan Email
// TODO: Cetak ringkasan email menggunakan method Summary()
}
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 File3Pointer 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 Pool12Konsep OOP Lanjutan
Pola Opsi FungsionalPola Builder di GoMethod ChainingAlias Tipe vs DefinisiDasar-Dasar ReflectionGambaran Umum Pembuatan KodeLatihan sendiri: Compiler Go online