Tasarım Kalıplarına Giriş
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 85 / 107.
Tasarım kalıpları, yazılım tasarımında ortaya çıkan yaygın sorunlara yönelik yeniden kullanılabilir çözümlerdir. Doğrudan kopyaladığın kodlar değil, belirli zorlukları çözmek için türlerini ve bunların etkileşimlerini nasıl yapılandıracağına rehberlik eden şablonlardır.
Tasarım kalıpları genellikle üç kategoriye ayrılır:
| Kategori | Amaç | Örnekler |
|---|---|---|
| Üretimsel | Nesne oluşturma mekanizmaları | Singleton, Factory, Builder |
| Yapısal | Türleri daha büyük yapılar hâlinde birleştirme | Adapter, Decorator, Composite |
| Davranışsal | Nesneler arasındaki iletişim | Observer, Strategy, Command |
Go'da tasarım kalıpları, geleneksel OOP dillerindekinden farklı görünür.
Sınıflar veya kalıtım olmadan Go, kalıpları arayüzler, struct gömme ve bileşim kullanarak uygular. Örneğin, Java'nın soyut bir sınıf kullanabileceği yerde Go bir arayüz kullanır. C++'ın kalıtım kullanabileceği yerde Go gömme kullanır.
Desenleri öğrenmek, yaygın sorunları tanımanıza ve çözümleri diğer geliştiricilerle etkili bir şekilde paylaşmanıza yardımcı olur. Birisi “burada Strateji desenini kullan” dediğinde, tüm ekip uzun açıklamalara gerek kalmadan yaklaşımı anlar.
Sonraki derslerde, Singleton ve Factory gibi yaratıcı tasarım kalıplarıyla başlayıp Observer ve Strategy gibi davranışsal tasarım kalıplarına geçerek Go'da birkaç temel kalıbı uygulayacaksın.
Görev
KolayTasarım kalıplarının kodu düzenlemeye nasıl yardımcı olduğunu gösteren basit bir bildirim sistemi oluşturalım! Gelecek derslerde Observer veya Strategy gibi kalıplarla kolayca genişletilebilecek bir yapı oluşturacaksın; ancak şimdilik iyi OOP ilkelerini izleyen temiz arayüzler ve türler kurmaya odaklan.
Kodunu üç dosyaya ayıracaksın:
notifier.go: Bildirim sistemin için temel arayüzü ve türleri tanımla.Notifieradında, doğrulama mesajı döndüren tek birSend(message string) stringmetoduna sahip bir arayüz oluştur.İki somut bildirim türü uygula:
EmailNotifier; birAddressalanına sahip olmalıdır.SendmetoduEmail to [address]: [message]döndürür.SMSNotifier; birPhoneNumberalanına sahip olmalıdır.SendmetoduSMS to [phone]: [message]döndürür.
dispatcher.go: Arayüz üzerinden herhangi bir bildirim türüyle çalışabilen bir dağıtıcı oluştur.Bir
NotificationDispatcherarayüzleri dilimi tutanNotifieryapısını oluştur. Aşağıdaki metotları ekle:- Bir bildirimi kaydetmek için
AddNotifier(n Notifier) - Mesajı kayıtlı tüm bildirim türleri üzerinden gönderen ve tüm doğrulama dizelerinden oluşan bir dilim döndüren
Broadcast(message string) []string
Ayrıca başlatılmış bir dağıtıcı döndüren bir
NewNotificationDispatcher()oluşturucusu da oluştur.- Bir bildirimi kaydetmek için
main.go: Bildirim türlerini ayarla ve mesajları yayınla.Oluşturulacak bildirim türlerinin sayısını oku. Her bildirim türü için türünü (
emailveyasms) ve hedefini (adres veya telefon numarası) oku. Her birini bir dağıtıcıya ekle.Ardından yayınlanacak bir mesaj oku. Bu mesajı tüm bildirim türleri üzerinden gönder ve her doğrulamayı kendi satırında yazdır.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Bildirim türlerinin sayısı
- Her bildirim türü için: tür (
emailveyasms), ardından hedef - Son satır: Yayınlanacak mesaj
Örneğin, aşağıdaki girdiler verildiğinde:
3
email
alice@example.com
sms
555-1234
email
bob@example.com
Server maintenance at midnightÇıktın şöyle olmalıdır:
Email to alice@example.com: Server maintenance at midnight
SMS to 555-1234: Server maintenance at midnight
Email to bob@example.com: Server maintenance at midnightVe aşağıdaki girdiler verildiğinde:
2
sms
555-9999
sms
555-0000
Meeting canceledÇıktın şöyle olmalıdır:
SMS to 555-9999: Meeting canceled
SMS to 555-0000: Meeting canceledBu yapı, arayüzlerin esnek ve genişletilebilir tasarımları nasıl mümkün kıldığını gösterir. Dağıtıcı, belirli bildirim türlerini bilmez. Yalnızca onların Send işlemini gerçekleştirebildiğini bilir. Bu, Observer ve Strategy gibi kalıpların üzerine inşa edildiği temeldir!
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Notifier sayısını oku
countStr, _ := reader.ReadString('\n')
count, _ := strconv.Atoi(strings.TrimSpace(countStr))
// Yeni bir dispatcher oluştur
dispatcher := NewNotificationDispatcher()
// Her notifier'ı oku ve dispatcher'a ekle
for i := 0; i < count; i++ {
notifierType, _ := reader.ReadString('\n')
notifierType = strings.TrimSpace(notifierType)
destination, _ := reader.ReadString('\n')
destination = strings.TrimSpace(destination)
// TODO: Türe göre uygun notifier'ı oluştur
// ve dispatcher'a ekle
// İpucu: notifierType değerinin "email" veya "sms" olup olmadığını kontrol et
}
// Yayınlanacak mesajı oku
message, _ := reader.ReadString('\n')
message = strings.TrimSpace(message)
// TODO: Mesajı yayınla ve her onayı 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