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

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

Merhaba,

Bu yazımızda Creational Patterns(Oluşturucu Kalıplar) kategorisine giren Abstract 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ı olduğumuz bir desen değildir Abstract Factory Design Pattern. O halde hemen ilk akla gelen “Factory Method D.P. ile Abstract Factory D.P. arasındaki fark nedir?” sorusuna cevap vermeyle konumuza başlayalım.

Factory Method D.P.; ilişkisel olan birden fazla nesnenin üretimini ortak bir arayüz aracılığıyla tek bir sınıf üzerinden yapılacak bir talep ile gerçekleştirmek ve nesne üretim anında istemcinin üretilen nesneye olan bağımlılığını sıfıra indirmeyi hedeflemektedir.

Abstract Factory D.P. ise ilişkisel olan birden fazla nesnenin üretimini tek bir arayüz tarafından değil her ürün ailesi için farklı bir arayüz tanımlayarak sağlamaktadır.

Yani anlayacağınız birden fazla ürün ailesi ile çalışmak zorunda kaldığımız durumlarda, istemciyi bu yapılardan soyutlamak için Abstract Factory D.P. doğru bir yaklaşım olacaktır.

Yapısal olarak Abstract Factory desenini detaylandırmak için siz aşağıdaki şemayı incelerken bende mantığını görselin altında kaleme almaya çalışayım.
C# Abstract Factory Design Pattern(Abstract Factory Tasarım Deseni)
Şemaya dikkat ederseniz kurguda birazdan detaylıca ele alacağımız “Abstract Factory”, “Abstract Product”, “Concrete Factory” ve “Concrete Product” aktörleri mevcuttur. Ama şöyle bir işlevselliği özetlememiz gerekirse eğer “Concrete Product” yapıları interface yahut abstract class olarak tanımlanmış “Abstract Product”lar tarafından implemente edilmektedirler. Bunların dışında fabrika sınıflarımızın implementasyonuyla ilgilenen ve yine interface yahut abstract class olarak tanımlanabilen “Abstract Factory” imzasıyla asıl fabrikalarımız olan “Concrete Factory” sınıflarımız türetilmektedir. Somut fabrikalarımız içerisinde implementasyondan gelen metotlar aracılığıyla ürünleri oluşturacak metotlar barındırılmakta ve bu fabrikalar ilişkisel olduğu ürünleri kendi bünyelerinde üretip geriye “Abstract Product” referansında return etmektedirler. En nihayetinde üretilen bu ilişkisel ürün ailesi Client tarafınada farklı bir sınıf aracılığıyla(Creater.cs ya da ApplicationClass.cs vs.) sunulmaktadır.

Bu izahatten sonra baş aktörlerimizi tek tek ele alalım;

  • Abstract Product
    Üretilecek ürünlerin soyut sınıfıdır. Belirli ürünlerin içerisindeki tüm member yapılanmasını imza olarak taşımakta ve Concrete Product yapılarına implemente etmektedir.
  • Concrete Product
    İstemcinin üretmek istediği ürün ailesinin gerçek somut sınıflarıdır.
  • Abstract Factory
    Ürün ailesini oluşturacak olan fabrika sınıflarına arayüz sağlayan yapıdır.
  • Concrete Factory
    Asıl ürün ailesini oluşturan fabrikalardır.

Burada dikkatinizi çekmek istediğim bir husus vardır ki o da Abstract Factory desenini uygularken size kolaylık sağlayacak bir mantıktan ibarettir. O mantık yukarıdaki aktörlerin sıralamasında gizlidir. Anlatmak istediğim Abstract Factory desenini uygularken inşa sürecinde oluşturma önceliği yukarıda olduğu gibi “Abstract Product” ile başlayarak sırasıyla “Concrete Product”, “Abstract Factory” ve son olarakta “Concrete Factory” şeklinde seyrederseniz deseni başarıyla uygulamış ve kurmuş olacaksınız.

Şimdi bir örnek senaryo üzerinden projemizi canlandıralım. Senaryomuzda; “Sql” ve “MySql” olmak üzere iki adet veritabanı söz konusudur. Bu veritabanları client tarafından talep edilirken; ilişkisel “Connection” ve “Command” nesneleri yani ürün aileleri oluşturulacaktır. Tabi bu işlemler yapılırken istemci sadece istediği veritabanıyla ilgilenecek, ürün ailesiyle olan tüm bağlar Abstract Factory ile soyutlanmış olacak ve üretimlerinden sorumlu olmayacaktır.

C# Abstract Factory Design Pattern(Abstract Factory Tasarım Deseni)
Yukarıdaki Class Diyagramından da gördüğünüz üzere senaryodaki “Connection ve “Command” nesneleri “Abstract Product”larımızken bunları implement eden “SqlConnection”, “MySqlConection”, “SqlCommand” ve “MySqlCommand” sınıfları ise “Concrete Product”lardır. Benzer şekilde fabrika sınıflarımız olan “Concrete Factory” nesnelerimiz ise “SqlDatabase” ve “MySqlDatabase” sınıflarıdır ve bunların kalıtım alacağı “Abstract Factory” sınıfı ise “DatabaseFactory” soyut sınıfıdır.

Şimdi desenimizi uygulamaya başlayalım. Tabi yukarılarda sizlere verdiğim sıralamayı göz önüne alarak bu işlemi gerçekleştireceğiz.

Adım 1
Öncelikle “Abstract Product”larımız olan “Connection” ve “Command” nesnelerini oluşturalım.

    //Abstract Product
    abstract class Connection
    {
        public abstract bool Connect();
        public abstract bool DisConnect();
        public abstract string State { get; }
    }
    //Abstract Product
    abstract class Command
    {
        public abstract void Execute(string query);
    }

Adım 2
Ardından “Concrete Product”larımız olan “SqlConnection”, “SqlCommand”, “MySqlConnection” ve “MySqlCommand” nesnelerini oluşturalım ve ilgili “Abstract Product”ları implement edelim.

    //Concrete Product
    class SqlConnection : Connection
    {
        public override string State => "Open";
        public override bool Connect()
        {
            Console.WriteLine("SqlConnection bağlantısı kuruluyor.");
            return true;
        }
        public override bool DisConnect()
        {
            Console.WriteLine("SqlConnection bağlantısı kesiliyor.");
            return false;
        }
    }
    //Concrete Product
    class SqlCommand : Command
    {
        public override void Execute(string query) => Console.WriteLine("SqlCommand sorgusu çalıştırıldı.");
    }
    //Concrete Product
    class MySqlConnection : Connection
    {
        public override string State => "Open";
        public override bool Connect()
        {
            Console.WriteLine("MySqlConnection bağlantısı kuruluyor.");
            return true;
        }
        public override bool DisConnect()
        {
            Console.WriteLine("MySqlConnection bağlantısı kesiliyor.");
            return false;
        }
    }
    //Concrete Product
    class MySqlCommand : Command
    {
        public override void Execute(string query) => Console.WriteLine("MySqlCommand sorgusu çalıştırıldı.");
    }

Adım 3
Şimdi sıra “Abstract Factory” yapımızı oluşturmaya geldi.

    //Abstract Factory
    abstract class DatabaseFactory
    {
        public abstract Connection CreateConnection();
        public abstract Command CreateCommand();
    }

Adım 4
Artık “Concrete Factory” sınıflarımızı oluşturabiliriz.

    //Concreate Factory
    class SqlDatabase : DatabaseFactory
    {
        public override Command CreateCommand() => new SqlCommand();
        public override Connection CreateConnection() => new SqlConnection();
    }
    //Concreate Factory
    class MySqlDatabase : DatabaseFactory
    {
        public override Command CreateCommand() => new MySqlCommand();
        public override Connection CreateConnection() => new MySqlConnection();
    }

Adım 5
Yapılan bu inşayı clienta sunacak Creater katmanını oluşturalım.

    //Creater
    class Creater
    {
        DatabaseFactory _databaseFactory;
        Connection _connection;
        Command _command;
        public Creater(DatabaseFactory databaseFactory)
        {
            _databaseFactory = databaseFactory;
            _connection = _databaseFactory.CreateConnection();
            _command = _databaseFactory.CreateCommand();

            Start();
        }

        void Start()
        {
            if (_connection.State == "Open")
            {
                _connection.Connect();
                _command.Execute("Select * from...");
                _connection.DisConnect();
            }
        }
    }

Adım 6
Client tarafından yaptığımız bu tasarıyı kullanarak ürün ailelerimizi oluşturalım.

    class Program
    {
        static void Main(string[] args)
        {
            Creater create = new Creater(new SqlDatabase());
            Console.WriteLine("**********");
            create = new Creater(new MySqlDatabase());
            Console.Read();
        }
    }

Ve projemizi derleyip çalıştırdığımızda aşağıdaki ekran görüntüsüyle karşılaşmaktayız.
C# Abstract Factory Design Pattern(Abstract Factory Tasarım Deseni).PNG

Anlayacağınız üzere birbiriyle ilişkili ürün ailesini oluştururken her bir product için özel bir arayüz tasarlanmakta ve bu arayüzler sayesinde ilgili ürün ilgili fabrikada oluşturulmaktadır. Fabrikaların ise ortak bir arayüzden türetilmesinin sebebi ise clienttan yapılacak talepte bağımlılığı ortadan kaldırmak içindir.

Sonraki yazılarım görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

1 Cevap

Bir yanıt yazın

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