Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

C# Composite Design Pattern(Composite Tasarım Deseni)

SENARYO 2
Bir şirkette aşağıdaki hiyerarşide personel pozisyonları bulunmaktadır.

  • Proje Yöneticisi
    • Takım Lideri
      • Yazılım Geliştirici

Her bir pozisyonda bulunan personel, hiyerarşik olarak kendisinden sonra gelen herhangi bir pozisyondaki personeli maiyetinde barındırabilmektedir.

Bu senaryoda herhangi bir pozisyondaki personelin, maiyetindeki personellerin bilgilerini ve toplam maaşlarını hesaplayıp karşılığına yazdıralım.

ÇÖZÜM
  • Adım 1 (Component Soyut Sınıfının Tasarlanması)
    Composite pattern’ın tasarımında ilk olarak Leaf ve Composite nesnelerimizin ortak arayüzü olan Component abstract class’ı tasarlanarak başlanmaktadır. Haliyle bizler de vakit kaybetmeksizin ilk olarak ilgili sınıfı oluşturarak başlıyoruz.

        //Component
        public abstract class Employee
        {
            protected string _name;
            protected double _salary;
            protected Employee(string name, double salary)
            {
                _name = name;
                _salary = salary;
            }
    
            public string GetName()
                => _name;
            public double GetSalary()
                => _salary;
            public abstract void Print();
        }
    

    Yukarıdaki ‘Employee’ adıyla tasarlanan Component sınıfı direkt Leaf ve Composite nesnelerinin kullanabileceği şekilde ortak member’larla tasarlanmıştır. Sadece Composite nesnelerine özel fonksiyonları barındıran Component tasarımı ise aşağıdaki olacaktır. Böylece hem Leaf nesnelerinde anlamsız member’lar olmayacak hem de arayüz ayrım prensibini sağlamış bulunacağız.

    Ayrıca yukarıdaki Component örneğinde ‘GetName’ ve ‘GetSalary’ metotlarının gövdeleri direkt oluşturulmuşken, ‘Print’ metodunun gövdesi concrete olacak olan Composite ve Leaf nesnelerine bırakılmıştır. Nihayetinde bu kod, buradaki davranışın ihtiyaca göre tarafımızca belirlendiğine bir örnektir. Misal bizim concrete nesnelerde maaşlarla ilgili ekstradan işlemler yapmamız gerekseydi ‘GetSalary’ metodu abstract olarak ayarlayıp, bu işi ilgili nesnesinde inşaya bırakabilirdik. Ama gerekmediği için kıssadan hisse yapıp gerekli işlemi burada gerçekleştirmekteyiz.

        //Component
        public abstract class EmployeeComposite : Employee
        {
            protected List<Employee> _employees = new();
            protected EmployeeComposite(string name, double salary) : base(name, salary)
            {
            }
            public void AddEmployee(Employee employee)
                => _employees.Add(employee);
            public void RemoveEmployee(Employee employee)
                => _employees.Remove(employee);
        }
    

    Composite nesneleri için özel olan fonksiyonları barındıran Component soyut sınıfımızda yukarıdaki gibi olacaktır. Burada da ‘AddEmployee’ ve ‘RemoveEmployee’ metotlarının gövdelerini aynı mantıkla concrete olan Composite nesnelerine bırakmaksızın direkt olarak inşa etmiş bulunmaktayız. Haliyle ilgili metotlar sadece ekleme ve çıkarma işlemleri yapacaklarından ve ekstra bir iş yürütmeyeceklerinden dolayı direkt bu ihtiyacı burada karşılamış bulunmaktayız.

  • Adım 2 (Composite Sınıfının Tasarlanması)
    Şimdi sıra, senaryo gereği altında en az bir pozisyondan personel barındıracak olan Composite sınıfını tasarlamaya gelmiş bulunmaktadır.

        //Component
        public class Manager : EmployeeComposite
        {
            public Manager(string name, double salary) : base(name, salary)
            {
            }
            public override void Print()
            {
                Console.WriteLine($"Name\t\t:{GetName()}");
                Console.WriteLine($"Salary\t\t:{GetSalary()}");
                double totalSalary = 0;
                _employees.ForEach(employee =>
                {
                    totalSalary += employee.GetSalary();
                    employee.Print();
                });
                Console.WriteLine($"Total Salary\t:{totalSalary}");
            }
        }
    

    Yukarıdaki ‘Manager’ isimli Component sınıfına göz atarsanız eğer ‘Print’ fonksiyonu ile ilgili personelin adını ve maaşını ekrana yazdırmakla birlikte altındaki elemanların da(ki bu elemanlar normal personel olabileceği gibi yönetici pozisyonunda bir personel de olabilir) toplam maaşını hesaplamakta ve ‘Print’ fonksiyonlarını tetikleyerek onlara dair bilgileri ekrana yazdırmaktadır.

  • Adım 3 (Leaf Sınıfının Tasarlanması)
    Şimdi ise altında herhangi bir pozisyondan personel barındırmayan personelleri temsil edecek olan Leaf sınıfını tasarlamaya sıra gelmiştir.

        //Leaf
        public class SoftwareDeveloper : Employee
        {
            public SoftwareDeveloper(string name, double salary) : base(name, salary)
            {
            }
            public override void Print()
            {
                Console.WriteLine($"\tName\t\t:{GetName()}");
                Console.WriteLine($"\tSalary\t\t:{GetSalary()}");
            }
        }
    

    Yukarıdaki ‘SoftwareDeveloper’ isimli Leaf nesnesinde ise ‘Print’ fonksiyonuyla sadece ilgili personele dair adı ve maaş bilgileri ekrana yazdırılmaktadır.

  • Adım 4 (Test)
    Bu ana kadar dikkat ederseniz; ‘Proje Yöneticisi’ ve ‘Takım Lideri’ pozisyonları ‘Manager’ sınıfıyla, ‘Yazılım Geliştirici’ pozisyonu ise ‘SoftwareDeveloper’ sınıfıyla temsil edilmektedir. Artık yapılan bu tasarımı rahatlıkla test edebiliriz.

            static void Main(string[] args)
            {
                Manager projectManager = new("Ahmet", 1000);
                Manager teamLeader1 = new("Mehmet", 500);
                Manager teamLeader2 = new("Hilmi", 450);
    
                SoftwareDeveloper softwareDeveloper1 = new("Çoşgun", 250);
                SoftwareDeveloper softwareDeveloper2 = new("Murat", 150);
                SoftwareDeveloper softwareDeveloper3 = new("Lale", 160);
                SoftwareDeveloper softwareDeveloper4 = new("Cümbüş", 270);
    
                teamLeader1.AddEmployee(softwareDeveloper1);
                teamLeader1.AddEmployee(softwareDeveloper2);
                teamLeader1.AddEmployee(softwareDeveloper3);
                teamLeader2.AddEmployee(softwareDeveloper4);
    
                projectManager.AddEmployee(teamLeader1);
                projectManager.AddEmployee(teamLeader2);
    
                projectManager.Print();
            }
    

    Yukarıdaki örnek kodu derleyip, çalıştırdığımızda aşağıdaki çıktıyı verecektir.
    C# Composite Design Pattern(Composite Tasarım Deseni)
    Görüldüğü üzere tüm pozisyonlardaki personellerin ve maiyetlerindeki diğer personellerin toplam maaşla birlikte bilgileri yazdırılmış bulunmaktadır.

İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir