Strategy Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 90 / 107.
Strategy kalıbı, bir algoritma ailesi tanımlamanıza, her birini kapsüllemenize ve çalışma zamanında birbirleriyle değiştirilebilir hâle getirmenize olanak tanır. Birden fazla nesnenin tek bir olaya tepki verdiği Observer kalıbının aksine Strategy, tek bir nesnenin farklı davranışlar arasında dinamik olarak geçiş yapmasını sağlar.
Go'da Strategy'yi, algoritma için bir arayüz tanımlayarak ve farklı uygulamaları bir bağlam yapısına enjekte ederek uygularız:
type PaymentStrategy interface {
Pay(amount float64) string
}
type CreditCard struct{}
func (c CreditCard) Pay(amount float64) string {
return fmt.Sprintf("Paid %.2f via Credit Card", amount)
}
type PayPal struct{}
func (p PayPal) Pay(amount float64) string {
return fmt.Sprintf("Paid %.2f via PayPal", amount)
}Bağlam yapısı, strateji arayüzüne bir başvuru tutarak bağlamın kodunu değiştirmeden algoritmanın değiştirilebilmesini sağlar:
type Checkout struct {
strategy PaymentStrategy
}
func (c *Checkout) SetStrategy(s PaymentStrategy) {
c.strategy = s
}
func (c *Checkout) ProcessPayment(amount float64) string {
return c.strategy.Pay(amount)
}Artık ödeme yöntemini çalışma zamanında değiştirebilirsiniz:
checkout := &Checkout{}
checkout.SetStrategy(CreditCard{})
fmt.Println(checkout.ProcessPayment(100.00)) // 100.00 Kredi Kartı ile ödendi
checkout.SetStrategy(PayPal{})
fmt.Println(checkout.ProcessPayment(50.00)) // 50.00 PayPal ile ödendiStrateji, bir işlemi gerçekleştirmenin birden fazla yolu olduğunda ve kullanıcı girdisine, yapılandırmaya veya çalışma zamanı koşullarına göre bunlardan birini seçmeniz gerektiğinde idealdir. Yaygın kullanım alanları arasında sıralama algoritmaları, sıkıştırma yöntemleri ve doğrulama kuralları bulunur.
Görev
KolayStrategy kalıbını kullanarak bir metin biçimlendirme sistemi oluşturalım! Çalışma zamanında değiştirilebilen farklı biçimlendirme stratejileri oluşturacaksın; böylece aynı metin işlemcisi, temel kodunu değiştirmeden farklı çıktı stilleri üretebilecek.
Kodunu üç dosyaya ayıracaksın:
formatter.go: Strateji arayüzünü ve somut biçimlendirme stratejilerini tanımla.Stratejinin kurallarına göre metni dönüştüren
TextFormattermetoduna sahip birFormat(text string) stringarayüzü oluştur.Üç biçimlendirme stratejisi uygula:
UppercaseFormatter: metni tamamen büyük harfe dönüştürürSnakeCaseFormatter: boşlukları alt çizgilere dönüştürür ve metni küçük harfe çevirirTitleFormatter: her kelimenin ilk harfini büyük yapar (kelimeler boşluklarla ayrılır)
processor.go: Biçimlendirme stratejisini kullanan bağlam yapını oluştur.Bir
TextProcessorstratejisi tutanTextFormatteryapısını oluştur. Şu metotları ekle:- Etkin biçimlendirme stratejisini değiştirmek için
SetFormatter(f TextFormatter) - Metne mevcut biçimlendiriciyi uygulayan
Process(text string) string
Ayrıca başlangıçta hiçbir biçimlendirici ayarlanmamış bir işlemci döndüren
NewTextProcessor()kurucusunu oluştur.- Etkin biçimlendirme stratejisini değiştirmek için
main.go: Çalışma zamanında stratejiler arasında geçiş yapmayı göster.Bir metin oku, ardından biçimlendirme işlemlerinin sayısını oku. Her işlem için biçim türünü (
upper,snakeveyatitle) oku, uygun biçimlendiriciyi işlemcine ayarla, özgün metni işle ve sonucu yazdır.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Biçimlendirilecek metin
- 2. satır: Biçimlendirme işlemlerinin sayısı
- Sonraki satırlar: Her işlem için biçim türü
Örneğin, şu girdi verildiğinde:
hello world today
3
upper
snake
titleÇıktın şu şekilde olmalıdır:
HELLO WORLD TODAY
hello_world_today
Hello World TodayŞu girdi verildiğinde:
Go Programming Language
2
snake
upperÇıktın şu şekilde olmalıdır:
go_programming_language
GO PROGRAMMING LANGUAGEŞu girdi verildiğinde:
design patterns are useful
1
titleÇıktın şu şekilde olmalıdır:
Design Patterns Are UsefulAynı TextProcessor nesnesinin, yalnızca biçimlendirici stratejisini değiştirerek nasıl tamamen farklı çıktılar ürettiğine dikkat et. İşlemci, hangi belirli biçimlendiriciyi kullandığını bilmez veya önemsemez. Yalnızca o anda ayarlanmış olan stratejiye yetki verir!
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Biçimlendirilecek metni oku
text, _ := reader.ReadString('\n')
text = strings.TrimSpace(text)
// İşlem sayısını oku
countStr, _ := reader.ReadString('\n')
count, _ := strconv.Atoi(strings.TrimSpace(countStr))
// Yeni bir metin işleyici oluştur
processor := NewTextProcessor()
// Her biçim işlemini işle
for i := 0; i < count; i++ {
formatType, _ := reader.ReadString('\n')
formatType = strings.TrimSpace(formatType)
// TODO: formatType'a göre ("upper", "snake" veya "title"),
// işlemciye uygun biçimlendiriciyi ayarla
// ve işlenmiş metni 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 PoolKendi başına pratik yap: Online Go derleyicisi