Kompozit Kalıbı
Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 61 / 70.
Composite deseni, nesneleri ağaç yapıları şeklinde düzenlemenize ve tekil nesneler ile nesne gruplarına tek tipte davranmanıza olanak tanıyan yapısal bir desendir. Hem tekil öğelerle hem de koleksiyonlarla aynı arayüz üzerinden çalışmak istediğiniz parça-bütün hiyerarşilerini temsil etmek için mükemmeldir.
Desen üç ana bileşene sahiptir: ortak işlemleri tanımlayan bir bileşen arayüzü, tekil nesneleri temsil eden yaprak sınıflar ve alt öğeleri içeren ve aynı arayüzü uygulayan bileşik sınıflar:
public interface IFileSystemItem
{
string Name { get; }
int GetSize();
}
public class File : IFileSystemItem
{
public string Name { get; }
private int _size;
public File(string name, int size)
{
Name = name;
_size = size;
}
public int GetSize() => _size;
}
public class Folder : IFileSystemItem
{
public string Name { get; }
private List<IFileSystemItem> _items = new List<IFileSystemItem>();
public Folder(string name) => Name = name;
public void Add(IFileSystemItem item) => _items.Add(item);
public int GetSize() => _items.Sum(item => item.GetSize());
}Bu desenin güzelliği, istemcilerin tek bir dosyayla mı yoksa tüm bir klasör hiyerarşisiyle mi çalıştıklarını bilmelerine gerek olmamasıdır:
var root = new Folder("root");
root.Add(new File("doc.txt", 100));
var subFolder = new Folder("images");
subFolder.Add(new File("photo.jpg", 500));
subFolder.Add(new File("icon.png", 50));
root.Add(subFolder);
Console.WriteLine(root.GetSize()); // 650Composite deseni; dosya sistemleri, UI bileşen ağaçları, organizasyon şemaları veya kapsayıcılar ile içeriklerin aynı şekilde ele alınması gereken her türlü yapı için idealdir. Basit ve karmaşık öğeler arasında ayrım yapma ihtiyacını ortadan kaldırarak istemci kodunu basitleştirir.
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ınabildiği bir yapı oluşturacaksınız; bu yapı, hiyerarşinin herhangi bir seviyesindeki toplam maaş maliyetini hesaplamanıza olanak tanıyacak.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
OrgComponent.cs:Organizationad alanı (namespace) içinde iki üyeye sahip birIOrgComponentarayüzü tanımlayın: birNameözelliği (string) ve tam sayı döndüren birGetSalary()metodu. Bu arayüz, hem bireysel çalışanların hem de departmanların izleyeceği ortak sözleşmeyi temsil eder.OrgClasses.cs: Aynı ad alanı içinde iki sınıf oluşturun:Employee- bireysel bir çalışanı temsil eden bir yaprak (leaf) sınıfı. Yapıcısında (constructor) bir isim ve maaş alır ve kendi maaşını döndürerek arayüzü uygular.Department- bir grubu temsil eden bir bileşik (composite) sınıf. Yapıcısında bir isim alır veIOrgComponentöğelerinden oluşan bir liste tutar. Üye eklemek için birAdd(IOrgComponent component)metodu ekleyin.GetSalary()metodu, tüm üyelerinin maaşlarının toplamını döndürmelidir.
Program.cs: Girdiye dayalı bir organizasyon yapısı oluşturun ve toplam maaşı hesaplayın. Departmanlar ve çalışanlar oluşturacak, bunları uygun şekilde iç içe yerleştirecek ve bileşik desenin tüm hiyerarşiyi nasıl tek tip olarak ele almanızı sağladığını göstereceksiniz.
Aşağıdaki girdileri alacaksınız:
- Oluşturulacak bileşen sayısı
- Her bileşen için: tür (
employeeveyadepartment), ardından isim ve çalışanlar için maaşları. Departmanlar için ayrıca üst departman adını (veya üst düzey bir departmansaroot) alacaksınız.
Her bileşen için girdi formatı:
employee
{name}
{salary}
{parent_department}
department
{name}
{parent_department}Yapıyı oluşturduktan sonra, kök departmanın toplam maaşını {root_name} Total Salary: {amount} formatında yazdırın.
Örneğin, girdiler şunlarsa:
5
department
Engineering
root
employee
Alice
5000
Engineering
employee
Bob
4500
Engineering
department
QA
Engineering
employee
Charlie
4000
QAÇıktı şöyle olmalıdır:
Engineering Total Salary: 13500Engineering departmanı Alice (5000), Bob (4500) ve QA departmanını içerir. QA ise Charlie (4000) içerir. Engineering üzerinde GetSalary() çağırdığınızda, tüm iç içe geçmiş bileşenlerden toplamı özyinelemeli olarak hesaplar - bu da Composite deseninin karmaşık ağaç yapılarıyla basit ve tek tip bir arayüz üzerinden çalışmanıza nasıl olanak tanıdığını gösterir!
Kopya kağıdı
Composite deseni, nesneleri ağaç yapıları şeklinde düzenleyen ve tekil nesneler ile grupları aynı arayüz üzerinden tek tip olarak ele alan yapısal bir desendir. Parça-bütün hiyerarşileri için idealdir.
Desenin üç ana bileşeni vardır:
- Bileşen arayüzü (Component interface): Ortak işlemleri tanımlar
- Yaprak sınıflar (Leaf classes): Tekil nesneleri temsil eder
- Kompozit sınıflar (Composite classes): Alt öğeleri içerir ve aynı arayüzü uygular
Temel uygulama örneği:
// Bileşen arayüzü
public interface IFileSystemItem
{
string Name { get; }
int GetSize();
}
// Yaprak sınıf
public class File : IFileSystemItem
{
public string Name { get; }
private int _size;
public File(string name, int size)
{
Name = name;
_size = size;
}
public int GetSize() => _size;
}
// Kompozit sınıf
public class Folder : IFileSystemItem
{
public string Name { get; }
private List<IFileSystemItem> _items = new List<IFileSystemItem>();
public Folder(string name) => Name = name;
public void Add(IFileSystemItem item) => _items.Add(item);
public int GetSize() => _items.Sum(item => item.GetSize());
}Kullanım - istemciler tekil öğelerle ve koleksiyonlarla tek tip bir şekilde çalışır:
var root = new Folder("root");
root.Add(new File("doc.txt", 100));
var subFolder = new Folder("images");
subFolder.Add(new File("photo.jpg", 500));
subFolder.Add(new File("icon.png", 50));
root.Add(subFolder);
Console.WriteLine(root.GetSize()); // 650Composite deseni; dosya sistemleri, kullanıcı arayüzü bileşen ağaçları, organizasyon şemaları veya kapsayıcılar ile içeriklerin aynı şekilde ele alınması gereken her türlü yapı için kullanışlıdır.
Kendin dene
using System;
using System.Collections.Generic;
using Organization;
class Program
{
public static void Main(string[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
// TODO: Departmanları isme göre saklamak için bir sözlük (dictionary) oluşturun
// Bu, bileşenleri eklerken üst departmanları bulmanıza yardımcı olacaktır
Dictionary<string, Department> departments = new Dictionary<string, Department>();
// TODO: Kök (root) departmanı takip edin
Department root = null;
for (int i = 0; i < n; i++)
{
string type = Console.ReadLine();
if (type == "department")
{
string name = Console.ReadLine();
string parent = Console.ReadLine();
// TODO: Departmanı oluşturun
// TODO: Onu departments sözlüğüne ekleyin
// TODO: Eğer parent "root" ise, bu kök departmandır
// TODO: Aksi takdirde, üst departmanı bulun ve bu departmanı ona ekleyin
}
else if (type == "employee")
{
string name = Console.ReadLine();
int salary = Convert.ToInt32(Console.ReadLine());
string parent = Console.ReadLine();
// TODO: Çalışanı oluşturun
// TODO: Üst departmanı bulun ve çalışanı ona ekleyin
}
}
// TODO: Kök departmanın toplam maaşını yazdırın
// Format: "{root_name} Total Salary: {amount}"
Console.WriteLine($"{root.Name} Total Salary: {root.GetSalary()}");
}
}
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
1OOP Temelleri
Harici Dosyalarİsim Alanları ve YönergelerSınıf ve Nesnelere Giriş'this' Anahtar KelimesiMetotlar ve ParametrelerAlanlar ve ÖzelliklerYapıcı MetotlarNesne BaşlatıcılarÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (:) Sözdizimi'base' Anahtar KelimesiVirtual ve Override Anahtar KelimeleriSealed Sınıflar'object' Temel SınıfıÖzet - Çalışan Hiyerarşisi7İleri Düzey Özellikler
Operatör Aşırı Yüklemeİndeksleyiciler (this[])ToString() Geçersiz KılmaGenişletme MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişThread-Safe SingletonFactory KalıbıObserver Kalıbı (Olaylar)Strategy Kalıbı2Özellikler ve Statik Üyeler
Otomatik Uygulanan ÖzelliklerSadece Okunur/Yazılır ÖzelliklerStatik Alanlar ve MetotlarStatik Sınıflarİfade Gövdeli Üyeler5Polimorfizm ve Arayüzler
Derleme vs Çalışma Zamanı PolimorfizmiArayüz vs Soyut SınıfÇoklu ArayüzlerBelirgin ArayüzlerUpcasting ve DowncastingÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kalıtım yerine KompozisyonGenerics (Sınıflar ve Metotlar)Delegates ve EventlerAttributes ve ReflectionIDisposable ve using İfadesiDependency Injection Temelleri11Tasarı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ı3Sınıf Mimarisi
Örnek vs Statik Veri'readonly' ve 'const' Anahtar KelimeleriDestekleyici Alanlar (Backing Fields)Özet - Banka Hesabı Yöneticisi6Kapsülleme
Erişim BelirleyicilerKapsülleme için ÖzelliklerVeri Gizleme UygulamasıDeğişmezlik KalıplarıÖzet - Öğrenci Kayıtları