C# Factory Method Design Pattern(Factory Method Tasarım Deseni)

Merhaba,
Creational Patterns (Oluşturucu Kalıplar) kategorisine giren Factory Method Design Pattern üzerine detaylı bir inceleme gerçekleştireceğiz. Factory Metod tasarım deseni, birbirleriyle ilişkili nesneleri oluşturmamızda bize oldukça alternatif bir metod sunmaktadır. Asıl amaç, oluşturmak istediğimiz sınıfın kendisinden bir örnek istemek yerine Factory Metod patterni sayesinde tek bir instance üzerinden gerekli nesnenin üretilmesini sağlamaktır.

Burada şöyle düşünebilirsiniz. Algoritmanızda belirli adımlarda farklı tiplerde nesnelere ihtiyacınız olabilir. Bu nesneleri if – else veyahut switch yapıları aracılığıyla, duruma göre oluşturabilirsiniz. Tabi bunu her seferinde yapmanın zaman ve kod açısından çok tasarruflu olduğunu düşünülemez. İşte böyle durumlarda Factory Method paternini kullanabilirsiniz.

Bir başka deyişle, elinizin altındaki birden çok ilişkisel sınıftan(veyahut Entityden) nesne üreteceksiniz, söz gelimi her defasında ilgili nesneye özel üretme gramerini uygulamanıza gerek kalmayaca, tek bir sınıf üzerinden oluşturacağınız nesne talebiyle istediğiniz nesneyi elde edebileceksiniz.

Bu işlemi gerçekleştirmek için “abstract class” ya da “interface” yapılarından faydalanacağız. Bu yapılardan faydalanmamızın sebebi, bu yapılardan kalıtım alan sınıfın, abstract ya da interface içerisindeki elemanı mecbur uygulamak zorunda kalmasıdır. Ama daha mühimi, farklı tipteki nesneleri oluşturmakla ilgilenmek zorunda kalmayacak olan Base Class’ımızın(ki bu sınıftan oluşturulmasını istediğimiz nesneleri türeteceğiz) oluşturduğu nesneyi Polymorphism(çok biçimlilik) aracılığı ile üst bir referanst türü ile işaretleyebilmektir.

C# Factory Method Design Pattern(Factory Method Tasarım Deseni)

C# Factory Method Design Pattern(Factory Method Tasarım Deseni)

Yukarıdaki şablonu inceleyerek bir senaryo çizelim. Tabi senaryomuzu ben bu paragrafta teorik olarak kurgulayacağım. Aşağıda benzer nitelikte farklı bir senaryo üzerinden Factory Method paternini uygulayacağız.

Yukarıdaki şablona göre elimizdeki birden fazla ürün interface tarafından türetilmektedir. Tabi yazımızın başında da belirttiğim gibi bu ürünleri abstract sınıf ile de türetebiliriz ki iki durumda da örneklendirme gerçekleştireceğiz.

İçerisinde geriye ilgili interface ya da abstract class tipinde değer geri dönen Factory işlemini gerçekleştirecek bir metod barındıran Creator sınıfımız mevcuttur. İstediğimiz ürünü oluşturabilmek için Creater tipinde bir nesne üzerinden Factory metodunu kullanmamız yeterli olacaktır. Factory metodu bize istediğimiz ürünün nesnesini oluşturacak ve interface ya da abstract class tipinde geri döndürecektir. Haliyle bizde interface ya da abstract class referansı üzerinden o nesneyi işaretleyebilecek ve gönül rahatlığıyla kullanabileceğiz.

Şimdi sıra pratik olarak Factory Method Design Patter’in nasıl yapıldığı üzerinde çalışmaya geldi. Hemen kurgulayacağım senaryoyu sizlerle paylaşmam gerekirse, ben bir oyun satıcısıyım ve “atari”, “pc” ve “ps” oyunları mevcut. Hadi gelin projemizi hemen dizayn edelim ve Factory Method paterni ile istediğimiz oyunu üretelim.

Abstract Class İle Factory Method Design Pattern

Öncelikle abstract sınıflarla Factory Design Pattern’i uygulamayı görelim.

Yukarıda kurguladığım senaryoya göre tüm ürünlerimi yani oyunlarımı türeteceğim abstract class’ı dizayn edelim.

    abstract class Oyun
    {
        public abstract void Platform();
    }

Şimdide ürünlerimizi tasarlayalım ve oluşturmuş olduğumuz “Oyun” abstract class’ından bu ürünleri türetelim.

    class Atari : Oyun
    {
        public override void Platform()
        {
            Console.WriteLine("Bu oyun ATARİ platformunda çalışmaktadır.");
        }
    }
    class PC : Oyun
    {
        public override void Platform()
        {
            Console.WriteLine("Bu oyun PC platformunda çalışmaktadır.");
        }
    }
    class PS : Oyun
    {
        public override void Platform()
        {
            Console.WriteLine("Bu oyun PS platformunda çalışmaktadır.");
        }
    }

Gördüğünüz gibi oyun ürünlerimin sınıflarını oluşturdum.

Artık bu sınıflardan nesne üretecek olan Creater sınıfını oluşturalım ve içerisine Factory işlemini yapacak metodumuzu tanımlayalım.

    class Creater
    {
        public Oyun FactoryMethod()
        {
          ...
        }
    }

Şimdi bu metodu tam olarak oluşturmadan önce bahsetmem gereken bir durum var. FactoryMethod’u bize istediğimiz tipte nesneyi oluşturup gönderek bir işleyişe sahip olacaktır dedik. “Eee anladık hocam da FactoryMethod benim istediğim nesneyi nereden bilecek?” diye sorarsanız eğer işte burada bunu Enumaration ile halledebiliriz. Aşağıdaki Enumaration FactoryMethod’un hangi tipte nesne üreteceğine yardımcı olacaktır.

    enum Oyunlar
    {
        Atari,
        PC,
        PS
    }

Bu işlemden sonra FactoryMethod’u tam olarak inşa edebiliriz.

    class Creater
    {
        public Oyun FactoryMethod(Oyunlar OyunTipi)
        {
            Oyun oyun = null;
            switch (OyunTipi)
            {
                case Oyunlar.Atari:
                    oyun = new Atari();
                    break;
                case Oyunlar.PC:
                    oyun = new PC();
                    break;
                case Oyunlar.PS:
                    oyun = new PS();
                    break;
            }
            return oyun;
        }
    }

Gördüğünüz gibi FactoryMethod parametresinde belirttiğimiz tipe göre istediğimiz nesneyi oluşturacak bir işleyişe sahip oldu. Burada dikkat etmeniz gereken husus, her bir oyun ürününün “Oyun” abstract class’ından kalıtım almasından dolayı çok biçimlilik kullanılarak “Oyun” referansında tutulabilmekte ve geriye döndürülebilmektedir.

Sıra geldi istediğimiz nesneyi üretmeye…

    class Program
    {
        static void Main(string[] args)
        {
            Creater creater = new Creater();
            Oyun atariOyunu = creater.FactoryMethod(Oyunlar.Atari);
            Oyun pcOyunu = creater.FactoryMethod(Oyunlar.PC);
            Oyun psOyunu = creater.FactoryMethod(Oyunlar.PS);

            atariOyunu.Platform();
            pcOyunu.Platform();
            psOyunu.Platform();

            Console.Read();
        }
    }

Çıktı olarak aşağıdaki ekran görüntüsüne göz atabilirsiniz.

C# Factory Method Design Pattern(Factory Method Tasarım Deseni)

C# Factory Method Design Pattern(Factory Method Tasarım Deseni)

Uzun lafın kısası, bu yaptığımız işlem tek bir Creater nesnesi üzerinden istediğimiz sınıfın nesnesini ürettirmek ve aşağıdaki uzun ve ilişkisiz nesne üretimlerini engellemektir.

            Atari atari = new Atari();
            PC pc = new PC();
            PS ps = new PS();

            atari.Platform();
            pc.Platform();
            ps.Platform();

Tabi ilişkisel sınıflar ve algoritmada ki ihtiyaca göre üretilmesi gereken sınıflar üzerinde bu tasarım desenini uygulamak en doğrusudur. Aksi halde diğer sınıfların nesnelerini bu şekilde üretmeniz daha makuldür.

Interface İle Factory Method Design Pattern

Eğer Factory Method tasarım desenenini interface kullanarak uygulamak istiyorsanız, “Oyun” isimli abstract sınıfını interface’e çevirmeniz yeterlidir. Tabi bu çevrim sırasında interface kurallarını dikkate almalı ve oyunları interfaceden türetirken yapılacak implementte override komutu olmadan uygulama gerçekleştirilmelidir.

Interface…

    interface Oyun
    {
        void Platform();
    }

Oyunlar…

    class Atari : Oyun
    {
        public void Platform()
        {
            Console.WriteLine("Bu oyun ATARİ platformunda çalışmaktadır.");
        }
    }
    class PC : Oyun
    {
        public void Platform()
        {
            Console.WriteLine("Bu oyun PC platformunda çalışmaktadır.");
        }
    }
    class PS : Oyun
    {
        public void Platform()
        {
            Console.WriteLine("Bu oyun PS platformunda çalışmaktadır.");
        }
    }

Interface ilede Factory Method Design Pattern’i bu şekilde tasarlanabilmektedir. Yani anlayacağınız abstract class ile olan tasarımdan, yapıların kendilerine has kullanım kuralları dışında hiçbir fark yoktur.

Hepinize iyi çalışmalar dilerim…
Sonraki yazılarımda görüşmek üzere…

Kaynak : https://www.youtube.com/watch?v=ajiT4d2mPzM, http://www.csharpnedir.com/articles/read/?id=146

Bunlar da hoşunuza gidebilir...

6 Cevaplar

  1. Samet dedi ki:

    Bunları yazıyorum aynı şekilde bir kaç hata çıkıyor enum başına public yazınca ve Oyun sınıfına atari pc ps tanıtınca hatalar düzeliyor. Ama bir sorun var. Çalıştırınca Sadece Bu oyun Atari oyunudur diyor 3 kere. Diğerlerini Yazmasını Sağlayamadım.

  2. Aykut DEMİRCİ dedi ki:

    Uzun uzadıya switch-case yapısına gerek kalmadan instance oluşturmak için şu yöntem kullanılabilir;

    class Creater
    {
        public Oyun FactoryMethod(Oyunlar OyunTipi)
        {
    		Type type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == OyunTipi.ToString());
    		Oyun oyun = (Oyun)Activator.CreateInstance(type);
    		return oyun;
        }
    }
    
  1. 20 Haziran 2017

    […] Factory Design Pattern üzerine konuşacağız. Aslında biz önceden bu desene benzer olan Factory Method Design Pattern üzerine bir makale ele almıştık. Yani mantıksal olarak ihtiyaç durumuna çokta yabancı […]

  2. 29 Aralık 2018

    […] programatik nesne üretimleri spesifik durumlarda oldukça etkili çözümler getirmekte veyahut Factory Design Pattern vs. gibi tasarım kalıplarında sınıf ismine olan birebir bağlılıktan bizleri […]

  3. 31 Ocak 2019

    […] sayesinde “CreateDbContext” isimli bir metodu implement etmekte ve içerik olarak Factory Method Design Pattern‘i kullanarak bizlere belirtilen tipte context nesnesi […]

  4. 18 Ağustos 2019

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*