Menu
Coddy logo textTech

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())  // 175

Composite, 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.

challenge icon

Görev

Kolay

Composite 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 OrgComponent arayüzü oluştur:

    • GetSalary() int: bu bileşenin toplam maaşını döndürür
    • GetName() 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) ve Name (int) alanlarına sahip bir Salary yapısı oluştur. GetSalary() kendi maaşını, GetName() ise kendi adını döndürür.

    Department (string) alanına ve Name öğelerini tutan bir Members dilimine sahip bir OrgComponent yapısı oluştur. Üye eklemek için bir Add(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: 165000

Ve 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: 125000

Ve aşağıdaki girdi verildiğinde:

2
Alice
50000
Bob
60000
0
1

Çıktın şöyle olmalıdır:

Bob: 60000

GetSalary() 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)
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online Go derleyicisi