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, tek tek nesneleri ve nesne gruplarını aynı şekilde ele almanızı sağlar. State, 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 kullanıcı arayüzü bileşenleri gibi hiyerarşik yapılar için mükemmeldir. Go'da hem tek tek öğelerin hem de kapsayıcıların uyguladığı ortak bir arayüz 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 (kapsayıcı), alt öğeleri barındırır ve 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 klasörlerin içine yerleştirebilirsin ve GetSize() çağrısı, bunun tek bir dosya ya da tüm bir dizin ağacı olmasına bakılmaksızın 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 tek tek nesnelere ve bileşimlere aynı şekilde davranmasını istediğinizde idealdir.
Görev
KolayComposite kalıbını kullanarak bir organizasyon şeması sistemi oluşturalım! Hem bireysel çalışanların hem de çalışanları veya başka departmanları içeren departmanların aynı şekilde ele alınabileceği bir yapı oluşturacaksın. Bu yapı, organizasyonun herhangi bir bölümündeki toplam maaşları hesaplamak için idealdir.
Kodunu üç dosyaya ayıracaksın:
component.go: Hem bireylerin hem de grupların uygulayacağı ortak arayüzü tanımla.İki metoda sahip bir
OrgComponentarayüzü oluştur:GetSalary() int: bu bileşenin toplam maaşını döndürürGetName() string: çalışanın veya departmanın adını döndürür
organization.go: Yaprak (bireysel çalışan) ve bileşik (departman) türlerinin her ikisini de uygula.Employee(string) veName(int) alanlarına sahip birSalaryyapısı oluştur.GetSalary()kendi maaşını,GetName()ise kendi adını döndürür.Department(string) alanına veNameöğelerini tutan birMembersdilimine sahip birOrgComponentyapısı oluştur. Üye eklemek için birAdd(c OrgComponent)metodu ekle.GetSalary(), tüm üyelerin maaşlarının toplamını döndürmeli;GetName()ise departmanın adını döndürmelidir.main.go: Bir organizasyon yapısı oluştur ve maaşları hesapla.Çalışan sayısını oku. Her çalışan için adını ve maaşını okuyarak
Employeeörnekleri oluştur. Ardından departman sayısını oku. Her departman için adını ve üye indekslerinin sayısını, ardından bu indeksleri oku (0 tabanlıdır ve oluşturulma sırasına göre daha önce oluşturulmuş çalışanlara veya departmanlara başvurur).Yapıyı oluşturduktan sonra son bir indeks oku ve bu bileşenin adını ve toplam maaşını şu biçimde yazdır:
[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 indeksleri
- Sorgulanacak son indeks
Örneğin, aşağıdaki girdi verildiğinde:
3
Alice
50000
Bob
60000
Carol
55000
1
Engineering
3
0
1
2
3Çıktın şöyle olmalıdır:
Engineering: 165000Ve aşağıdaki girdi verildiğinde:
4
Alice
50000
Bob
60000
Carol
55000
Dave
70000
2
Dev
2
0
1
QA
2
2
3
4Çıktın şöyle olmalıdır:
QA: 125000Ve aşağıdaki girdi verildiğinde:
2
Alice
50000
Bob
60000
0
1Çıktın şöyle olmalıdır:
Bob: 60000GetSalary() metodunun tek bir çalışan veya tüm bir departman üzerinde çağrıldığında nasıl aynı şekilde çalıştığına dikkat et! Composite kalıbı, aynı arayüz üzerinden bireyleri ve grupları aynı şekilde ele almanı sağlar.
Kendin 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'e 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'e 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'e 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 PoolKendi başına pratik yap: Online Go derleyicisi