Go'da Builder Deseni
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 80 / 107.
Builder Pattern, karmaşık bir nesnenin oluşturulmasını temsilinden ayırır. Functional Options deseninin aksine Builder, nesneyi adım adım yapılandıran yöntemlere sahip özel bir builder yapısı kullanır.
Bir HTTP isteği için builder'ı şu şekilde uygulayabilirsin:
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
}Her yöntem, oluşturucu işaretçisini döndürerek yöntem zincirlemeyi mümkün kılar. Build() yöntemi işlemi tamamlar ve oluşturulan nesneyi döndürür:
req := NewRequestBuilder().
Method("POST").
URL("https://api.example.com").
Header("Content-Type", "application/json").
Build()Builder deseni, nesneler birden fazla yapılandırma adımı gerektirdiğinde veya belirli bir oluşturma sırasını zorunlu kılmak istediğinizde öne çıkar. Özellikle değişmez nesneler oluşturmak ya da oluşturma sürecinin kendisinin doğrulanması gerektiğinde kullanışlıdır.
Görev
KolayBuilder Pattern'ı kullanarak bir e-posta mesajı oluşturucu geliştirelim! E-posta mesajlarının alıcılar, CC, konu, gövde ve ekler gibi birçok isteğe bağlı bileşeni vardır; bu da onları yöntem zincirleme ile adım adım oluşturmak için mükemmel bir aday hâline getirir.
Kodunuzu iki dosyaya ayıracaksınız:
email.go: E-posta yapınızı ve oluşturucusunu tanımlayın.Şu alanlara sahip bir
Emailyapısı oluşturun:from(string)to(string dilimi)cc(string dilimi)subject(string)body(string)
Oluşturulmakta olan bir Email işaretçisini tutan bir
EmailBuilderyapısı oluşturun. Başlatılmış bir Email (NewEmailBuilder()vetoiçin boş dilimler) içeren yeni bir oluşturucu döndürenccişlevini uygulayın.Aşağıdaki oluşturucu yöntemlerini ekleyin; her biri zincirleme için
*EmailBuilderdöndürmelidir:From(address string)- göndereni ayarlarTo(address string)-todilimine bir alıcı eklerCC(address string)-ccdilimine bir alıcı eklerSubject(subject string)- konu satırını ayarlarBody(body string)- e-posta gövdesini ayarlar
Oluşturulan
Build()değerini döndüren bir*Emailyöntemi ekleyin.Son olarak, Email üzerine aşağıdaki biçimde bir string döndüren bir
Summary()yöntemi ekleyin:From: [from] To: [comma-separated to addresses] CC: [comma-separated cc addresses or "none"] Subject: [subject] Body: [body]main.go: Oluşturucuyu kullanarak e-posta mesajları oluşturun ve görüntüleyin.Gönderen adresini, ardından alıcı sayısını ve her bir alıcı adresini okuyun. Sonra CC alıcılarının sayısını ve her bir CC adresini okuyun. Son olarak konuyu ve gövdeyi okuyun.
E-postayı oluşturmak için yöntem zincirleme ile EmailBuilder'ı kullanın, ardından özetini yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Gönderen adresi
- 2. satır: Alıcı sayısı
- Sonraki satırlar: Her bir alıcı adresi
- Sonraki satır: CC alıcılarının sayısı
- Sonraki satırlar: Her bir CC adresi
- Sonraki satır: Konu
- Son satır: Gövde
Örneğin, şu girdi verildiğinde:
alice@company.com
2
bob@company.com
carol@company.com
1
manager@company.com
Weekly Report
Please find the weekly report attached.Çıktınız şu olmalıdır:
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.Ve şu girdi verildiğinde:
support@service.com
1
customer@email.com
0
Your Ticket Update
Your support ticket has been resolved.Çıktınız şu olmalıdır:
From: support@service.com
To: customer@email.com
CC: none
Subject: Your Ticket Update
Body: Your support ticket has been resolved.Oluşturucunun, tekrarlanan To() çağrıları aracılığıyla birden fazla alıcıyı birer birer eklemenize nasıl olanak tanıdığına ve isteğe bağlı birçok alan olsa bile bu kalıbın oluşturma sürecini nasıl temiz ve okunabilir tuttuğuna dikkat edin.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Gönderen adresini oku
from, _ := reader.ReadString('\n')
from = strings.TrimSpace(from)
// Alıcı sayısını oku
toCountStr, _ := reader.ReadString('\n')
toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))
// Her alıcı adresini oku
toAddresses := make([]string, toCount)
for i := 0; i < toCount; i++ {
addr, _ := reader.ReadString('\n')
toAddresses[i] = strings.TrimSpace(addr)
}
// CC alıcı sayısını oku
ccCountStr, _ := reader.ReadString('\n')
ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))
// Her CC adresini oku
ccAddresses := make([]string, ccCount)
for i := 0; i < ccCount; i++ {
addr, _ := reader.ReadString('\n')
ccAddresses[i] = strings.TrimSpace(addr)
}
// Konuyu oku
subject, _ := reader.ReadString('\n')
subject = strings.TrimSpace(subject)
// Gövdeyi oku
body, _ := reader.ReadString('\n')
body = strings.TrimSpace(body)
// TODO: E-postayı oluşturmak için EmailBuilder'ı method chaining ile kullan
// NewEmailBuilder() ile başla, ardından From(), To(), CC(), Subject(), Body() zincirle
// Son olarak Email'i almak için Build() çağır
// TODO: Summary() metodunu kullanarak e-posta özetini yazdır
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker Pool12İleri Düzey OOP Kavramları
Functional Options DeseniGo'da Builder DeseniMetot ZincirlemeTür Takma Adları vs. TanımlamalarReflection TemelleriKod Üretimine Genel BakışKendi başına pratik yap: Online Go derleyicisi