Bu yazıda “Creational” desenler grubunun en önemli ve en sık kullanılan deseni olan Abstract Factory(Soyut Fabrika) tasarım deseninin C# ile ne ÅŸekilde uygulandığını bir örnek üzerinden göstereceÄŸiz.
İlk yazımda da bahsettiÄŸim gibi “Creational” grubundaki desenler bir yada daha çok nesnenin çeÅŸitli ÅŸekillerde oluÅŸturulması ile ilgili desenlerdir. Bu kategoride ele alınan “Abstract Factory” ise birbirleriyle iliÅŸkili yada birbirlerine baÄŸlı olan nesnelerin oluÅŸturulmasını en etkin bir ÅŸekilde çözmeyi hedefler. Bu hedefe ulaÅŸmak için soyut sınıflardan(abstract class) veya arayüzlerden(interface) yoÄŸun bir ÅŸekilde faydalanmaktadır. “Abstract Factory” deseninin ana teması belirli sınıfların içerdiÄŸi ortak arayüzü soyut bir sınıf yada arayüz olarak tasarlamaktır. Böylece nesneleri üreten sınıf, hangi nesnenin üretileceÄŸi ile pek fazla ilgilinmesi gerekmez. İlgilenmesi gereken nokta oluÅŸturacağı nesnenin hangi arayüzleri desteklediÄŸi yada uyguladığıdır. Bahsi geçen mekanizmalarla deseni oluÅŸturduÄŸumuz anda çalışma zamanında hangi nesnenin oluÅŸturulması gerektiÄŸini bilmeden nesnelerin oluÅŸturulmasını yönetebiliriz.
EÄŸer bir nesne oluÅŸturacaksanız ve tam olarak hangi nesnenin oluÅŸturulacağına bir switch yada if deyimi ile karar veriyorsanız muhtemelen her nesneyi oluÅŸtruduÄŸunuzda aynı switch yapısını kullanmak zorunda kalacaksınız. Bu tür tekrarları önlemek için “Abstarct Factory” deseninden faydalanılabilir. Bu elbetteki nesnelerin ortak bir arayüzü uygulamış olma zorunluluÄŸunun getirdiÄŸi bir faydadır.
Åžimdi de gerçek dünyadan bir örnek vererek “Abstract Factory” deseninin hangi durumlarda kullanabileceÄŸimizi ve soyut fabrika mantığını netleÅŸtirelim. Bir CD sürücüsü düşünün. CD sürücüsü kendisine sürülen CD leri okumakla sorumludur. Hiç bir zaman sürülen CD nin ÅŸekli ve biçimiyle ilgilenmez. Ama sürülen CD nin okunabilmesi için de belirli ÅŸartların yerine getirildiÄŸini farzeder. Yani siz CD sürücüsüne CD olmayan ama CD ye benzeyen bir cisim yerleÅŸtiriseniz onu da okumaya çalışır.(eÄŸer CD sürücünüz bozulmazsa!) Çünkü okumaya çalıştığı cismin ne olduÄŸu ile pek ilgilenmez CD sürücüsü. Buradaki örnekte CD sürücüsünün okuma yapabilmesi için gereken ÅŸartları bir soyut fabrika sınıfı ile modelleyebiliriz. Kare yada daire ÅŸeklindeki gerçek CD ler ise bu soyut fabrika sınıfı tarafından belirlenen ÅŸartları destekleyen gerçek nesnelerdir. CD sürücüsünün kendisi ise soyut fabrika tarafından belirlenen standartlar çerçevesi içerisinde CD nin ne tür bir CD olduÄŸundan bağımsız bir ÅŸekilde bilgiyi okuyan birimdir. Bu, “abstract factory” desenindeki client yani istemci sınıfa denk düşer ki bu sınıf nesnelerin yaratılmasından sorumludur.
Bu giriÅŸ bilgilerinden sonra “abstract factory” deseninin temel özelliklerini kısaca özetleyelim.
- “Abstract Factory”, nesneleri oluÅŸturan bir sınıftır. OluÅŸturulan bu nesneler birbirleriyle iliÅŸkili olan nesnelerdir. DiÄŸer bir deyiÅŸle aynı arayüzü uygulamış olan nesnelerdir.
- Üretilen nesnelerin kendisiyle ilgilenilmez. İlgilenilen nokta oluşturulacak nesnelerin sağladığı arayüzlerdir. Dolayısıyla aynı arayüzü uygulayan yeni nesneleri desene eklemek çok kolay ve esnektir.
- Bu desende üretilecek nesnelerin birbirleriyle ilişkili olması beklenir.
UML Modeli
AÅŸağıdaki ÅŸekil “abstract factory” tasarım deseninin yapısal UML diagramını göstermektedir. Åžemadaki her bir ÅŸekil desendeki bir sınıfı modellemektedir. Ayrıca desendeki sınıflar arasındaki iliÅŸkilerde detaylı bir ÅŸekilde gösterilmiÅŸtir.

Yukarıda ÅŸemayı kısaca açıklamakta fayda var. Åžemadan da görüleceÄŸi üzere “abstract factory” deseninde 3 ana yapı vardır. İlk yapı nesnelerin oluÅŸturulmasından sorumlu soyut ve gerçek fabrikalar, ikinci yapı soyut fabrikadan türeyen gerçek fabrikaların ürettiÄŸi ürünleri temsil eden soyut ve gerçek ürün sınıflar, son yapı ise herhangi bir ürünü, kendisine parametre olarak verilen soyut fabrikaları kullanarak üreten istemci(client) sınıfıdır.
SoyutFabrika sınıfı gerçek fabrikaların uygulaması gereken arayüzü temsil eder. Bu sınıf, bütün metotları soyut olan sınıf olabileceÄŸi gibi bir arayüz de olabilir. Uygulamanızın ihtiyacına göre dilediÄŸinizi kullanabilirsiniz. SoyutFabrika sınıfında ürün1 ve ürün2′nin üretilmesinden sorumlu iki tane metot bulunmaktadır. Dolayısıyla bütün gerçek fabrikaların hem ürün1′i hemde ürün’yi ürettiÄŸi kabul edilmektedir. Her bir ürünün ortak özelliklerini belirlemek ve ana yapıda toplamak için SoyutUrun1 ve SoyutUrun2 sınıfları oluÅŸturulur. Bu sınıflarda herhangi bir ürüne özel bilgi bulunmamaktadır. Asıl bilgi bu soyut ürünlerden türeyen GercekUrun sınıflarında bulunmaktadır. Her bir fabrikanın ürettiÄŸi ürünleri modelleyen sınıflarda yukarıdaki ÅŸekilde gösterilmiÅŸtir. Asıl önemli mesele ise gerçek fabrikaların üretimden sorumlu metotlarının ne ÅŸekilde geri döneceÄŸidir. Yukarıdaki ÅŸemadan da görüleceÄŸi üzere bu metotlar üreteceÄŸi ürünün soyut sınıfına dönmektedir. Yani üretim sonucunda geri dönen gerçek ürün nesnesi deÄŸildir. Åžemada Client olarak gösterilen sınıfın yapısı ise ÅŸu ÅŸekildedir : Client sınıfı yapıcı metoduna bir soyut fabrika nesnesi alır. Ve soyut fabrikanın üretimden sorumlu metotlarını kullanarak soyut ürünleri üretir. Dikkat ederseniz Client sınıfı hangi gerçek fabrikanın üretim yaptığından ve üretilen ürünün gerçek özelliklerinden haberi yoktur. Client sadece soyut fabrikanın içerdiÄŸi temel özelliklerin farkındadır. Bunu ÅŸemadaki kalın ve kesikli oklardan görmek mümkündür.
Desenin C# ile Gerçekleştirilmesi
Yukarıdaki yapısal örneği verdikten sonra gerçek bir örnek ile bu deseni nasıl gerçekleştirebileceğimizi inceleyelim. Bu örnekte araba kasası ve araba lastiği üreten farklı iki firmanın üretimi modellenmektedir.
Önce örneği kabaca inceleyin, ardından açıklamaları okuyun.
|
using System;
namespace DesignPattern
{
    abstract class SoyutArabaFabrikasi
    {
        abstract public SoyutArabaKasasi KasaUret();
        abstract public SoyutArabaLastigi LastikUret();
    }
    class MercedesFabrikasi : SoyutArabaFabrikasi
    {
        public override SoyutArabaKasasi KasaUret()
        {
            return new MercedesE200();
        }
        public override SoyutArabaLastigi LastikUret()
        {
            return new MercedesLastik();
        }
    }
    class FordFabrikasi : SoyutArabaFabrikasi
    {
        public override SoyutArabaKasasi KasaUret()
        {
            return new FordFocus();
        }
        public override SoyutArabaLastigi LastikUret()
        {
            return new FordLastik();
        }
    }
    abstract class SoyutArabaKasasi
    {
        abstract public void LastikTak(SoyutArabaLastigi a );
    }
    abstract class SoyutArabaLastigi
    {
    }
    class MercedesE200 : SoyutArabaKasasi
    {
        public override void LastikTak(SoyutArabaLastigi lastik)
        {
            Console.WriteLine( lastik + ” lastikli MercedesE200″);
        }
    }
    class FordFocus : SoyutArabaKasasi
    {
        public override void LastikTak(SoyutArabaLastigi lastik)
        {
            Console.WriteLine( lastik + ” lastikli FordFocus”);
        }
    }
    class MercedesLastik : SoyutArabaLastigi
    {
    }
    class FordLastik : SoyutArabaLastigi
    {
    }
    class FabrikaOtomasyon
    {
        private SoyutArabaKasasi ArabaKasasi;
        private SoyutArabaLastigi ArabaLastigi;
        public FabrikaOtomasyon( SoyutArabaFabrikasi fabrika )
        {
            ArabaKasasi = fabrika.KasaUret();
            ArabaLastigi = fabrika.LastikUret();
        }
        public void LastikTak()
        {
            ArabaKasasi.LastikTak( ArabaLastigi );
        }
    }
    class UretimBandi
    {
        public static void Main()
        {
            SoyutArabaFabrikasi fabrika1 = new MercedesFabrikasi();
            FabrikaOtomasyon fo1 = new FabrikaOtomasyon( fabrika1 );
            fo1.LastikTak();
            SoyutArabaFabrikasi fabrika2 = new FordFabrikasi();
            FabrikaOtomasyon fo2 = new FabrikaOtomasyon( fabrika2 );
            fo2.LastikTak();
        }
    }
} |
Yukarıdaki örnekte SoyutArabaFabrikasi sınfı iki metot içermektedir. Bu metotlar SoyutArabaFabrikasi sınıfından türeyecek sınıfların uygulaması gereken metotlardır. Çünkü metotlar abstract olarak bildirilmiştir. Bu metotlar gerçek fabrika sınıflarının araba kasası ve araba lastiği üretmesi gerektiğinin belirtisidir. Zira görüldüğü üzere SoyutArabaFabrikasi sınıfından türeyen MercedesFabrikasi ve FordFabrikasi kendilerine has lastikleri ve kasaları üretmek için soyut fabrika sınıfının metotlarını kullanmaktadır. Bu metotlar geri dönüş değeri olarak soyut ürün sınıflarını temsil eden sınıfları döndürmektedirler. Örneğin KasaUret() metodu her bir fabrika için farklı ürün üretmesine rağmen her bir ürün SoyutArabaKasasi sınıfındaki metotları uyguladığı için gerçek ürünler birbirleyile ilişkili hale gelir. Mercedes fabrikası KasaUret() metodu ile MercedesE200 ürününü döndürmesine rağmen Ford fabrikası aynı metotla FordFocus ürününü döndürmektedir. Ancak her iki fabrikanın da ürettiği ürün SoyutArabaKasasi sınıfından türediği için herhangi bir çelişki olmamaktadır.
SoyutArabaKasasi sınıfındaki LastikTak() sınıfı fabrikadan üretilen ürünlerin birbirleriyle karıştırılmadan esnek bir şekilde nasıl ilişkilendirildiğini gösterilmektedir. Bu metot parametre olarak gerçek lastik ürünü yerine soyut lastik ürünü alır. Dolayısıyla herhangi bir fabrikadan üretilen lastik ürünü bu metoda parametre olarak geçirilebilir.
FabrikaOtomasyon sınıfı kendisine verilen bir soyut fabrika nesnesi üzerinden kasa ve lastik üretir ve üretilen lastiği, lastiğin gerçek türünü bilmeden üretilen araba kasası ile ilişkilendirir. Dikkat ederseniz bu sınıf üretimin yapılacağı fabrikanın hangi fabrika olduğu ve üretilen ürünlerin gerçekte hangi ürünler olduğu ile ilgilenmez.
Son olarak tasarladığımız bütün bu sınıfları test edecek UretimBandı sınıfını inceleyelim. Bu sınıf içerisinde ürünleri üretilecek fabrikanın soyut nesnesi oluşturulur ve FabrikaOtomasyonu nesnesine parametre olarak verilir. SoyutFabrika nesnesini alan FabrikaOtomasyonu bu nesnenin standart üretimden sorumlu metotlarını kullanarak kasa ve lastik üretir. Ardından SoyutArabaKasasi sınıfının LastikTak() metodunu kullanarak kasa ve lastik ürünlerini ilişkilendirir.
Yorumlar
Yorum Yok
Yorumunuzu Ekleyin
Yorum eklemek için giris yapmalısınız.