Kompozit Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 96 / 107.
Composite deseni, tekil nesneleri ve nesne gruplarını tek tipte ele almanıza olanak tanır. State deseni davranışı dahili duruma göre değiştirirken, Composite hem yaprakların hem de kapsayıcıların aynı arayüzü paylaştığı ağaç yapıları oluşturur.
Bu desen; dosya sistemleri, organizasyon şemaları veya UI bileşenleri gibi hiyerarşik yapılar için mükemmeldir. Go'da, hem bireysel öğelerin hem de kapsayıcıların uyguladığı ortak bir interface tanımlarız:
type Component interface {
GetSize() int
}
type File struct {
Name string
Size int
}
func (f File) GetSize() int {
return f.Size
}Bileşik (konteyner), alt öğeleri barındırır ve onların sonuçlarını bir araya getirerek aynı arayüzü uygular:
type Folder struct {
Name string
Children []Component
}
func (f *Folder) Add(c Component) {
f.Children = append(f.Children, c)
}
func (f Folder) GetSize() int {
total := 0
for _, child := range f.Children {
total += child.GetSize()
}
return total
}Artık klasörleri iç içe yerleştirebilirsiniz ve GetSize() fonksiyonunu çağırmak, ister tek bir dosya ister tüm bir dizin ağacı olsun, aynı şekilde çalışır:
docs := &Folder{Name: "docs"}
docs.Add(File{Name: "readme.txt", Size: 100})
docs.Add(File{Name: "notes.txt", Size: 50})
root := &Folder{Name: "root"}
root.Add(docs)
root.Add(File{Name: "config.json", Size: 25})
fmt.Println(root.GetSize()) // 175Composite, parça-bütün hiyerarşilerini temsil etmeniz gerektiğinde ve istemcilerin tekil nesneler ile kompozisyonlara aynı şekilde davranmasını istediğinizde idealdir.
Görev
KolayComposite desenini kullanarak bir organizasyon şeması sistemi oluşturalım! Hem bireysel çalışanların hem de departmanların (çalışanları veya diğer departmanları içeren) tek tip olarak ele alınabileceği bir yapı oluşturacaksınız; bu, organizasyonun herhangi bir bölümündeki toplam maaşları hesaplamak için mükemmeldir.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
component.go: Hem bireylerin hem de grupların uygulayacağı ortak arayüzü (interface) tanımlayın.İki yöntemi olan bir
OrgComponentarayüzü oluşturun:GetSalary() int— bu bileşen için toplam maaşı döndürürGetName() string— çalışanın veya departmanın adını döndürür
organization.go: Hem yaprak (bireysel çalışan) hem de bileşik (departman) türlerini uygulayın.Name(string) veSalary(int) alanlarına sahip birEmployeeyapısı (struct) oluşturun.GetSalary()yöntemi kendi maaşını,GetName()yöntemi ise adını döndürür.Name(string) alanına veOrgComponentöğelerini tutan birMembersdilimine (slice) sahip birDepartmentyapısı oluşturun. Üye eklemek için birAdd(c OrgComponent)yöntemi ekleyin.GetSalary()yöntemi tüm üyelerin maaşlarının toplamını döndürmeli veGetName()departman adını döndürmelidir.main.go: Bir organizasyon yapısı oluşturun ve maaşları hesaplayın.Çalışan sayısını okuyun. Her çalışan için adını ve maaşını okuyarak
Employeeörnekleri oluşturun. Ardından departman sayısını okuyun. Her departman için adını ve üye dizini sayısını, ardından bu dizinleri (0 tabanlı, oluşturulma sırasına göre önceden oluşturulmuş çalışanlara veya departmanlara atıfta bulunarak) okuyun.Yapıyı oluşturduktan sonra, son bir dizin okuyun ve o bileşenin adını ve toplam maaşını şu formatta yazdırın:
[name]: [salary]
Aşağıdaki girdiler sağlanacaktır:
- Çalışan sayısı, ardından her çalışanın adı ve maaşı ayrı satırlarda
- Departman sayısı, ardından her departmanın adı, üye sayısı ve üye dizinleri
- Sorgulanacak son dizin
Örneğin, şu girdi verildiğinde:
3
Alice
50000
Bob
60000
Carol
55000
1
Engineering
3
0
1
2
3Çıktınız şu olmalıdır:
Engineering: 165000Ve şu girdi verildiğinde:
4
Alice
50000
Bob
60000
Carol
55000
Dave
70000
2
Dev
2
0
1
QA
2
2
3
4Çıktınız şu olmalıdır:
QA: 125000Ve şu girdi verildiğinde:
2
Alice
50000
Bob
60000
0
1Çıktınız şu olmalıdır:
Bob: 60000GetSalary() yönteminin ister tek bir çalışan ister tüm bir departman üzerinde çağrılsın nasıl aynı şekilde çalıştığına dikkat edin; Composite deseni, bireyleri ve grupları aynı arayüz üzerinden tek tip olarak ele almanıza olanak tanır!
Kopya kağıdı
Composite deseni, tekil nesneleri ve nesne gruplarını ortak bir arayüz aracılığıyla tek tip olarak ele alır. Dosya sistemleri, organizasyon şemaları veya kullanıcı arayüzü (UI) bileşenleri gibi hiyerarşik yapılar için idealdir.
Hem tekil öğelerin hem de kapsayıcıların uyguladığı ortak bir arayüz tanımlayın:
type Component interface {
GetSize() int
}Yaprağı (tekil öğe) uygulayın:
type File struct {
Name string
Size int
}
func (f File) GetSize() int {
return f.Size
}Alt öğeleri tutan ve sonuçlarını birleştiren kompoziti (kapsayıcı) uygulayın:
type Folder struct {
Name string
Children []Component
}
func (f *Folder) Add(c Component) {
f.Children = append(f.Children, c)
}
func (f Folder) GetSize() int {
total := 0
for _, child := range f.Children {
total += child.GetSize()
}
return total
}Tekil öğelerin ve kompozisyonların tek tip ele alınışını gösteren kullanım örneği:
docs := &Folder{Name: "docs"}
docs.Add(File{Name: "readme.txt", Size: 100})
docs.Add(File{Name: "notes.txt", Size: 50})
root := &Folder{Name: "root"}
root.Add(docs)
root.Add(File{Name: "config.json", Size: 25})
fmt.Println(root.GetSize()) // 175Kendin dene
package main
import "fmt"
func main() {
// Çalışan sayısını oku
var numEmployees int
fmt.Scanln(&numEmployees)
// Tüm bileşenleri (çalışanlar ve departmanlar) oluşturulma sırasına göre sakla
var components []OrgComponent
// TODO: Her çalışanın adını ve maaşını oku
// Employee örnekleri oluştur ve bunları components dilimine ekle
for i := 0; i < numEmployees; i++ {
var name string
var salary int
fmt.Scanln(&name)
fmt.Scanln(&salary)
// TODO: Çalışan oluştur ve components'a ekle
}
// Departman sayısını oku
var numDepartments int
fmt.Scanln(&numDepartments)
// TODO: Her departmanın adını, üye sayısını ve üye indekslerini oku
// Department örnekleri oluştur, üyeleri indekse göre ekle ve components'a ekle
for i := 0; i < numDepartments; i++ {
var deptName string
var memberCount int
fmt.Scanln(&deptName)
fmt.Scanln(&memberCount)
// TODO: Departman oluştur, üye indekslerini oku, üyeleri ekle, components'a ekle
}
// Sorgulanacak son indeksi oku
var queryIndex int
fmt.Scanln(&queryIndex)
// TODO: Bileşenin adını ve toplam maaşını şu formatta yazdır: [name]: [salary]
// Örnek: fmt.Printf("%s: %d\n", name, salary)
}
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ı11Standart Kütüphane ve OOP
io.Reader ve io.Writersort.Interface Arayüzüfmt.Stringer ArayüzüStruct'lar ile encoding/jsonhttp.Handler ArayüzüÖzet - REST API Modelleri14Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıDekoratör olarak Middleware3İş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