Menu
Coddy logo textTech

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 ödendi

Strateji, 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.

challenge icon

Görev

Kolay

Strategy 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 TextFormatter metoduna sahip bir Format(text string) string arayüzü oluştur.

    Üç biçimlendirme stratejisi uygula:

    • UppercaseFormatter: metni tamamen büyük harfe dönüştürür
    • SnakeCaseFormatter: boşlukları alt çizgilere dönüştürür ve metni küçük harfe çevirir
    • TitleFormatter: 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 TextProcessor stratejisi tutan TextFormatter yapı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.

  • 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, snake veya title) 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 Useful

Aynı 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
		
	}
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online Go derleyicisi