Design patterns notları -2- composite pattern

Composite pattern hiyerarşileri düzenler. Bu hiyerarşiye en güzel örnek, amir-memur hiyerarşisidir. En tepede bir amir bulunur. Sonra onun altında bir memur. Bu memur aynı zamanda amirdiri, onun da memurları vardır. Bu böyle en alt seviyedeki memura kadar gider. 

Composite pattern bu türlü yapıları ele almak için kullanılır. UML şeması aşağıdaki gibidir:

IComponent: Hem amirlerin hem de memurların referans aldığı interface'dir. Her ikisi için de aynı interface'i kullanıyoruz çünkü memurlar da amir olabilir. Örneğin bir dekan; rektörün memyuru olup, bölüm başkanının da amiridir.

Composite: İçinde IComponent listesinin bulunduğu sınıf yani amir.

Component: Altında ICompotent listesi olmayan son memur diyebiliriz

Yapacağımız örnek Projenin class diagram'ı aşağıdaki gibidir. Projeyi buradan indirebilirsiniz.

Şimdi örnek projemize başlayabiliriz. Boş bir console application açtıktan sonra ilk olarak projeye IPersonel.cs sınıfını ekliyoruz.

namespace CompositePattern
{
    public interface IPersonel
    {
        //hem memur hem de amir aslında birer personeldir.
        
        string Göster(int derinlik);
        void Ekle(IPersonel seviye);
        IPersonel Bul(int Id);
        IPersonel Sil(int Id);
        string İsim { getset; }
        int Id { getset; }
    }
}

Şimdi sırada Kök sınıfının oluşturulmasında. Projeye Amir.cs sınıfını ekliyoruz.

namespace CompositePattern
{
    public class Amir : IPersonel
    {
        public string İsim { getset; }
        // Bu amir'in adı
        public int Id { getset; }
        // amir'in id'si
        List<IPersonel> Memurlar = null;
        //amir'in memurları
        IPersonel ÜstSeviye = null;
        //amirin'ün amiri
 
        public Amir(string isim, int id)
        {
            İsim = isim;
            Id=id;
            Memurlar = new List<IPersonel>();
        }
 
        public void Ekle(IPersonel personel)
        {
            Memurlar.Add(personel);
            // amir'in altına memur ekliyoruz.
        }
 
        public IPersonel Sil(int id)
        {
            ÜstSeviye = this;
            //bulunduğumuz amir'in en üst seviye olduğunu düşünüyoruz.
 
            IPersonel p = ÜstSeviye.Bul(id);
            //bulunduğumuz amirin altında id parametresiyle bir memur arıyoruz.
 
            if (ÜstSeviye != null//Amir varsa
            {
                (ÜstSeviye as Amir).Memurlar.Remove(p);
                // Memurlar  içinden p memurunu siliyoruz.
                return ÜstSeviye;
            }
            else
                return this;
        }
 
 
        public IPersonel Bul(int id)
        {
            ÜstSeviye = this;
            if (Id.Equals(id))
            {
                return this;
                // Eğer aranan bulunduğumuz amir ise onu döndürür
            }
 
            IPersonel bulunan = null;
 
            foreach (IPersonel personel in Memurlar)
            {
                bulunan = personel.Bul(id);
 
                // Recursive bir şekilde bulunduğumuz amir'ün memurlarını ve onların memurlarını, onların memurlarının memurlarını... arar
                if (bulunan != null)
                    break;
                // aranan personel bulununca arama durur.  ya da memurların tamamı gezilince durur.
            }
            return bulunan;
        }
 
        public string Göster(int seviye)
        {
            StringBuilder s = new StringBuilder(new String('-', seviye));
            s.Append(İsim+"\n");
            foreach (IPersonel memur in Memurlar)
            {
                s.Append(memur.Göster(seviye + 2));
            }
            return s.ToString();
 
            //derinliğe göre memurları listeler.
        }
    }
}

Amir'i oluşturduktan sonra sıra Memur'a geliyor.

namespace CompositePattern
{
    public class Memur : IPersonel
    {
        public string İsim { getset; }
        public int Id { getset; }
 
        public Memur(string isim, int id)
        {
            İsim = isim;
            Id = id;
        }
 
        public void Ekle(IPersonel personel)
        {
            Console.WriteLine("Bu memurun altına memur eklenemez çünkü amir olamaz");
        }
 
        public IPersonel Sil(int id)
        {
            Console.WriteLine("Bu memur doğrudan silinemez ancak amiri silebilir.");
            return this;
        }
 
        public string Göster(int seviye)
        {
            return new String('-', seviye) + İsim + "\n";
        }
 
        public IPersonel Bul(int id)
        {
            if (id.Equals(Id))
                return this;
            else
                return null;
        }
    }
}

Tüm bu sorulardan sonra projedeki Program.cs içinde aşağıdaki kodlar ile pattern'i deniyoruz.

namespace CompositePattern
{
    class program
    {
        static void Main()
        {
            IPersonel personel1 = new Amir("İsim1", 1);
            IPersonel personel2 = new Amir("İsim2", 2);
            IPersonel personel3 = new Amir("İsim3", 3); 
            IPersonel personel4 = new Amir("İsim4", 4); 
            IPersonel personel5 = new Amir("İsim5", 5);
            IPersonel personel6 = new Amir("İsim6", 6); 
 
            IPersonel personel7 = new Memur("İsim7", 7); 
            IPersonel personel8 = new Memur("İsim8", 8); 
            IPersonel personel9 = new Memur("İsim9", 9); 
            IPersonel personel10 = new Memur("İsim10", 10); 
            IPersonel personel11 = new Memur("İsim11", 11); 
            IPersonel personel12 = new Memur("İsim12", 12);
 
            personel1.Ekle(personel2);
            personel2.Ekle(personel3);
            personel2.Ekle(personel4);
            personel3.Ekle(personel5);
            personel5.Ekle(personel6);
            personel5.Ekle(personel7);
            personel5.Ekle(personel8);
            personel5.Ekle(personel9);
            personel6.Ekle(personel10);
            personel4.Ekle(personel11);
            personel4.Ekle(personel12);
 
            Console.Write(personel1.Göster(0));
        }
    } 
}

Programı çalıştırınca aşağıdaki ekran görüntüsünü alacaksınız.

2 thoughts on “Design patterns notları -2- composite pattern

  1. mesut Reply

    Kıdemli ogrenci bir şey diyecem ama gaza gelme :D

    Bugun iş yerinde arkadaş composite pattern kullanagiz dedi. Dedim neymiş o? Bana bu linki verdi. İnsanın arkadaşı, arkadaşının linkini verince hoş oluyormuş. Çalışmaya devam. Bekleme yapma!

Leave a Reply

Your email address will not be published. Required fields are marked *