Factory Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 87 / 107.
Factory deseni, nesne oluşturma işlemini ayrı bir fonksiyona veya metoda devrederek, oluşturma mantığını açığa çıkarmadan örnekler oluşturmanıza olanak tanır. Örnek sayısını kontrol eden Singleton'ın aksine Factory, girdi parametrelerine dayalı esnek nesne oluşturmaya odaklanır.
Go'da bir fabrika (factory), genellikle bir arayüz (interface) türü döndüren ve birleşik bir API aracılığıyla farklı somut türler oluşturmanıza olanak tanıyan bir fonksiyondur:
type Notifier interface {
Send(message string) string
}
type EmailNotifier struct{}
type SMSNotifier struct{}
func (e EmailNotifier) Send(message string) string {
return "Email: " + message
}
func (s SMSNotifier) Send(message string) string {
return "SMS: " + message
}
func NewNotifier(notifierType string) Notifier {
switch notifierType {
case "email":
return EmailNotifier{}
case "sms":
return SMSNotifier{}
default:
return EmailNotifier{}
}
}NewNotifier fabrika fonksiyonu, hangi somut türün oluşturulacağı kararını kapsüller. İstemci kodu, belirli uygulamadan habersiz kalarak yalnızca Notifier arayüzü ile çalışır:
notifier := NewNotifier("sms")
result := notifier.Send("Hello!") // "SMS: Hello!"Bu desen; çalışma zamanı koşullarına bağlı olarak nesneler oluşturmanız gerektiğinde, karmaşık başlatma mantığını merkezileştirmek istediğinizde veya istemci kodunu değiştirmeden kolayca yeni türler eklemeniz gerektiğinde öne çıkar. Sadece arayüzü (interface) uygulayan yeni bir struct ekleyin ve fabrika fonksiyonunu (factory function) güncelleyin.
Görev
KolayFactory desenini kullanarak bir belge dönüştürücü sistemi inşa edelim! Hedef formata göre farklı belge dönüştürücüler üreten bir fabrika oluşturacaksınız; bu sayede istemci kodu, birleşik bir arayüz aracılığıyla herhangi bir dönüştürücü ile çalışabilecektir.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
converter.go: Dönüştürücü arayüzünüzü ve somut uygulamalarınızı tanımlayın.Belge içeriğini alan ve dönüştürülmüş çıktıyı döndüren
Convert(content string) stringmetoduna sahip birConverterarayüzü oluşturun.Üç dönüştürücü türü uygulayın:
PDFConverter—Convertmetodu"PDF: " + contentdöndürürHTMLConverter—Convertmetodu"HTML: <p>" + content + "</p>"döndürürMarkdownConverter—Convertmetodu"MD: # " + contentdöndürür
Format dizesine (
"pdf","html"veya"markdown") bağlı olarak uygun dönüştürücüyü döndüren birNewConverter(format string) Converterfabrika fonksiyonu oluşturun. Tanınmayan herhangi bir format için varsayılan olarak birPDFConverterdöndürün.main.go: Dönüştürücüler oluşturmak ve belgeleri işlemek için fabrikanızı kullanın.Bir format türü ve belge içeriği okuyun. Uygun dönüştürücüyü oluşturmak için fabrikayı kullanın, ardından içeriği dönüştürün ve sonucu yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Format türü (
"pdf","html","markdown"veya başka bir şey) - Satır 2: Dönüştürülecek belge içeriği
Örneğin, şu girdi verildiğinde:
html
Welcome to Go ProgrammingÇıktınız şu olmalıdır:
HTML: <p>Welcome to Go Programming</p>Ve şu girdi verildiğinde:
markdown
Chapter OneÇıktınız şu olmalıdır:
MD: # Chapter OneVe şu girdi verildiğinde:
pdf
Annual Report 2024Çıktınız şu olmalıdır:
PDF: Annual Report 2024Ve şu girdi verildiğinde:
docx
Meeting NotesÇıktınız şu olmalıdır:
PDF: Meeting NotesAna kodun belirli dönüştürücü türleri hakkında bilgi sahibi olmasına gerek kalmadığına dikkat edin; sadece fabrikadan bir dönüştürücü ister ve arayüzü kullanır. Bu, istemci kodunu değiştirmeden daha sonra yeni formatlar eklemeyi kolaylaştırır!
Kopya kağıdı
Factory deseni, nesne oluşturma işlemini ayrı bir fonksiyona devreder ve oluşturma mantığını açığa çıkarmadan örnekler oluşturmanıza olanak tanır. Giriş parametrelerine dayalı esnek nesne oluşturmaya odaklanır.
Bir factory fonksiyonu, bir arayüz (interface) türü döndürerek birleşik bir API aracılığıyla farklı somut türlerin oluşturulmasını sağlar:
type Notifier interface {
Send(message string) string
}
type EmailNotifier struct{}
type SMSNotifier struct{}
func (e EmailNotifier) Send(message string) string {
return "Email: " + message
}
func (s SMSNotifier) Send(message string) string {
return "SMS: " + message
}
func NewNotifier(notifierType string) Notifier {
switch notifierType {
case "email":
return EmailNotifier{}
case "sms":
return SMSNotifier{}
default:
return EmailNotifier{}
}
}İstemci kodu yalnızca arayüzle çalışır ve belirli uygulamalardan habersiz kalır:
notifier := NewNotifier("sms")
result := notifier.Send("Hello!") // "SMS: Hello!"Bu desen; çalışma zamanı koşullarına göre nesneler oluşturmanız gerektiğinde, karmaşık başlatma mantığını merkezileştirmek istediğinizde veya istemci kodunu değiştirmeden yeni türler eklemeniz gerektiğinde kullanışlıdır.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Format türünü oku
scanner.Scan()
format := scanner.Text()
// Belge içeriğini oku
scanner.Scan()
content := scanner.Text()
// TODO: Uygun dönüştürücüyü oluşturmak için factory'yi kullanın
// TODO: İçeriği dönüştürün ve sonucu yazdırın
fmt.Println(result)
}
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 Pool