Abstract Factory Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 88 / 107.
Abstract Factory deseni, somut türlerini belirtmeden birbiriyle ilişkili nesne aileleri oluşturarak Factory desenini genişletir. Tek bir fabrika fonksiyonu yerine, her biri birbiriyle ilişkili nesnelerden oluşan tutarlı bir set üreten ve birden fazla somut fabrikanın uyguladığı bir fabrika arayüzü tanımlarsınız.
Düğmeler ve onay kutuları oluşturması gereken bir UI araç setini düşünün. Farklı işletim sistemleri farklı uygulamalar gerektirir, ancak bileşenlerin tutarlı bir şekilde birlikte çalışması gerekir:
type Button interface {
Render() string
}
type Checkbox interface {
Check() string
}
// Soyut fabrika arayüzü
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}Her bir somut fabrika, birbiriyle ilişkili bileşenlerden oluşan bir aile üretir:
// Windows ailesi
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }
type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }
type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }
// Mac ailesi
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }
type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }
type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }İstemci kodu, somut uygulamalardan bağımsız kalarak fabrika arayüzü ile çalışır:
func BuildUI(factory GUIFactory) {
button := factory.CreateButton()
checkbox := factory.CreateCheckbox()
fmt.Println(button.Render(), checkbox.Check())
}Sisteminizin birbiriyle ilişkili birden fazla ürün ailesiyle çalışması gerektiğinde ve aynı aileden bileşenlerin birlikte kullanıldığından emin olmak istediğinizde Abstract Factory kullanın. Basit bir Factory'den daha karmaşıktır, bu nedenle yalnızca ürün ailelerini yönetmeye gerçekten ihtiyaç duyduğunuzda ona başvurun.
Görev
KolayAbstract Factory desenini kullanarak bir mobilya mağazası sistemi inşa edelim! Birbiriyle ilişkili mobilya ürün aileleri üreten fabrikalar oluşturacaksınız; her fabrika tutarlı bir stil (Modern veya Vintage) üreterek aynı fabrikadan çıkan sandalye ve masaların estetik olarak eşleşmesini sağlar.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
furniture.go: Ürün arayüzlerinizi ve somut mobilya türlerinizi tanımlayın.İki ürün arayüzü oluşturun:
SitOn() stringmetoduna sahipChairPlaceItems() stringmetoduna sahipTable
İki mobilya ailesi uygulayın:
- Modern ailesi:
ModernChair,Sitting on a sleek modern chairdöndürür veModernTable,Placing items on a glass modern tabledöndürür - Vintage ailesi:
VintageChair,Sitting on an ornate vintage chairdöndürür veVintageTable,Placing items on a wooden vintage tabledöndürür
factory.go: Soyut fabrika arayüzünüzü ve somut fabrikalarınızı tanımlayın.İki metodlu bir
FurnitureFactoryarayüzü oluşturun:CreateChair() ChairCreateTable() Table
İki somut fabrika uygulayın:
ModernChairveModernTableüretenModernFactoryVintageChairveVintageTableüretenVintageFactory
Ayrıca, stile (
modernveyavintage) bağlı olarak uygun fabrikayı döndüren birGetFactory(style string) FurnitureFactoryfonksiyonu oluşturun. Tanınmayan stiller için varsayılan olarakModernFactorydöndürün.main.go: Odaları döşemek için fabrikalarınızı kullanın.Fabrikayı kullanarak bir sandalye ve masa oluşturan, ardından her iki eylemi ayrı satırlarda gösteren formatlanmış bir dize döndüren bir
FurnishRoom(factory FurnitureFactory) stringfonksiyonu oluşturun.Bir stil girdisi okuyun, uygun fabrikayı alın, bir odayı döşeyin ve sonucu yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Mobilya stili (
modern,vintageveya başka bir şey)
Örneğin, şu girdi verildiğinde:
modernÇıktınız şu olmalıdır:
Sitting on a sleek modern chair
Placing items on a glass modern tableVe şu girdi verildiğinde:
vintageÇıktınız şu olmalıdır:
Sitting on an ornate vintage chair
Placing items on a wooden vintage tableVe şu girdi verildiğinde:
rusticÇıktınız şu olmalıdır:
Sitting on a sleek modern chair
Placing items on a glass modern tableFurnishRoom fonksiyonunun arayüz aracılığıyla herhangi bir fabrikayla nasıl çalıştığına dikkat edin; modern mi yoksa vintage mobilya mı oluşturduğunu bilmez. Bu, bir odadaki tüm mobilyaların aynı aileden gelmesini sağlayarak tutarlı bir stili korur!
Kopya kağıdı
Abstract Factory deseni, somut türlerini belirtmeden ilgili nesne aileleri oluşturur. Birden fazla somut fabrikanın uyguladığı bir fabrika arayüzü tanımlar ve her biri tutarlı bir ilgili nesne kümesi üretir.
Yapı
Her nesne türü için ürün arayüzlerini tanımlayın:
type Button interface {
Render() string
}
type Checkbox interface {
Check() string
}Her ürün türünü oluşturmak için yöntemler bildiren bir soyut fabrika arayüzü oluşturun:
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}Somut Uygulamalar
Her ailenin tutarlı bir stile veya davranışa sahip olduğu somut ürün ailelerini uygulayın:
// Windows ailesi
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }
type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }
type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }
// Mac ailesi
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }
type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }
type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }İstemci Kodu
İstemci kodu, somut uygulamalardan bağımsız kalarak fabrika arayüzü ile çalışır:
func BuildUI(factory GUIFactory) {
button := factory.CreateButton()
checkbox := factory.CreateCheckbox()
fmt.Println(button.Render(), checkbox.Check())
}Ne Zaman Kullanılmalı
Sisteminizin birden fazla ilgili ürün ailesiyle çalışması gerektiğinde ve aynı aileden bileşenlerin birlikte kullanıldığından emin olmak istediğinizde Abstract Factory kullanın. Basit bir Factory'den daha karmaşıktır, bu nedenle yalnızca ürün ailelerini yönetmeye gerçekten ihtiyaç duyduğunuzda kullanın.
Kendin dene
package main
import "fmt"
// FurnishRoom mobilya oluşturmak için bir fabrika kullanır ve sonucu döndürür
// TODO: Bu fonksiyonu uygula
// - Sandalye ve masa oluşturmak için fabrikayı kullan
// - İlk satırda SitOn() sonucunu ve ikinci satırda PlaceItems() sonucunu içeren bir dize döndür
func FurnishRoom(factory FurnitureFactory) string {
// TODO: Fabrikayı kullanarak sandalye ve masa oluştur
// TODO: Her iki eylemi de ayrı satırlarda içeren formatlanmış dizeyi döndür
return ""
}
func main() {
var style string
fmt.Scanln(&style)
// TODO: Stile göre uygun fabrikayı al
// TODO: Fabrikayı kullanarak bir odayı döşe
// TODO: Sonucu 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 Pool