Abstract Factory Tasarım Deseni

header_abstract_factory

Yaratımsal desen kategorisinde yer alan diğer bir desen ise abstract factory desenidir.Bu desenin birbiriyle ilişkili veya bağlı olan sınıfların (nesne ailelerinin) üretiminin tek bir arayüz veya soyut sınıf ile yapılmasını sağlar.Böylece tek bir sınıf ile istenilen nesne aileleri üretilmiş olur.

Bu desen için verilen en popüler örnek veritabanı provider yapısıdır.Veri odalı bir yazılım sisteminin veritabanı olarak MS-SQL kullandığını varsayın ve veri işlemleri için doğrudan framework tarafından sağlanan SQL sınıflarını kullandım.Bu kod yazış biçimi bizi aşırı bağımlı bir yapıya götürüyor.Sistemimizin veri kaynağının değişmeyeceğini öngörüyor olsak bile framework sınıfları wrap edecek sınıflar yazmamız gerekir.Yazılım kaynağının değişeceğini ya da sistem içerisinde bazı modüllerin Oracle bağlantısına göre bazı modüllerinin ms-sql veritabanına göre davranması gerekebilir.Bu bahsettiğim senaryo aslında bir veri erişim modelinin (Connection,Command,Transaction) diğer bir deyişle ürün ailesinin farklı tiplerde olabileceğini farklı versiyonlarının olacağını görüyoruz.Bu gibi senaryolar da soyut fabrika desenini kullanabiliriz.Bu senaryoya ait örnek kod parçasına buradan ulaşabilirsiniz

Benzer yapı .NET Base Library içerisinde yer alıyor.

untitled

Genel olarak soyut fabrika deseni ;

  1. İlişkisi veya bağlılığı bulunan nesnelerin üretimi efektif ve kolay bir şeklide gerçekleşir.
  2. İstemci doğrudan asıl ürünle konuşmaz.Asıl ürüne erişmek istediğinde onun için tanımlı olan arayüz ile konuşur.Böylelikle ürün ailesindeki değişiklikler istemci kodunda herhangi bir değişikliğe ihtiyaç duymaz.Aynı zamanda daha test edilebilir bir yapı ortaya çıkmış olur.
  3. Asıl ürünlerden soyutlanmış sınıflar veya arayüzler üzerinden kullanıldığı için kolayca başka nesne grupları gerekli implementasyonlar yapıldığı takdirde desen içerisine ve üretime dahil edilmiş olur.
  4. Birbiri ile ilişkileri olan nesneleri üretimini soyutlamak için sorumlu işlem methodlarında basit if-else , switch ifadelerini kullanarak da gerçekleştirebiliriz.Fakat bu tarz bir kodlama değişim ve ekleme işlemleri için sıkı kod yazılmasını beraberinde getirebileceği gibi işlem methodların sorumluluk alanının dışına çıkılmış olunur.Üretimde if-switch gibi alt seviye kodlar kullanılmadığı için değişimlere kolayca ayak uydurur.
  5. Factory method deseni yerine soyut fabrika desenini kullanabiliriz.
  6. Genel olarak fabrika method sınıflarını genelleştirmek için kullanılır.

 Tasarım

Aşağıda desenin UML diagramını görüyoruz.

capture

 

Desene ait bazı kavramlar ;

Concrete Product; Birbiriyle ilişkisi bulunan nesneler ve asıl üretilmesi istenilen nesnelerdir. (ProductA1 , ProductA2 , ProductB1 , ProductB2)

Abstract Product; birbiriyle ilişkisi bulunan sınıfları tek bir tip altında tanımlayabilmek için kullanılır.Concrete product  sınıfları tarafından uygulanır veya implement edilir.İnterface ve abstract class olarak yazılabilirler. (IProductA , IProductB)

Concrete Factory ; İçerisinde nesne ailesine ilişkin concrete product nesnelerinin üretiminde sorumlu methodları içerir.Asıl fabrika sınıflarıdır.Bu sınıf abstract factory sınıfını gerçekleştirirler.(Factory1 , Factory2)

Abstract Factory ; Factory sınıfları için soyut bir tip sağlar ve içerisinde yine abstract product sınıfları için methodlar bulunur. (IFactory)

Bir kaç tasarım alternatifleri

  • Burada nesnelerin oluşturulması concrete factory sınıfları içerisinde gerçekleşir.Nesne oluşturma sürecini burada istediğiniz gibi  kurgulayabilirsiniz. Örneğin nesne oluşturmak için Dependency Injection gibi yapıları kullanabilirsiz
  • Factory sınıflarının fazla olduğu durumlar da generic bir factory sınıfı kullanabilirsiniz.
  • Delegate tabanlı factory sınıfları tasarlayabilirsiniz.
  • Yazacağınız fabrika sınıflarının istemci kod tarafından doğrudan kullanılması yerine bunun için bir wrapper sınıf yazarak tek bir factory tipi ile o ürün ailesi ile ilgili tüm alt sınıfların üretilmesini ve ilgili temel işlemlerin yapılmasını sağlayabilirsiniz.

Örnek Senaryo ve kodlama

Raporlama ile ilgili örnek bir senaryomuz var.Bir online bankacılık uygulmasın da müşterilerin günlük veya aylık gibi çeşitli periyotlarda hesap hareketlerini alabildiği bir fonksiyonellik düşünün.Teknik olarak elimde bir veri seti var ve bu veri setini seçeneğe göre excel veya pdf olarak bir çıktı üretmem gerekiyor.Bu ihtiyaç için iş çatısının (business framework) ilgili yerine bu fonksiyonelliği sağlayacak kodları yazıyoruz.Aşağıda başlangıçta kullanacağım kodlarım yer alıyor

Kodlara baktığınızda rapor tipinden bağımsız olarak 3 işlemsel fonksiyonum (ReportConnector,ReportFormatter,ReportWriter) var.Bunlar bir ürün ailesini temel fonksiyonları ve bunların kalıtımı sonucunda PDF ve excel için iki farklı ürün ailesi elde ediyoruz.

Yukarıda fabrika sınıflarının kodlamalarını göreceksiniz.Ek olarak bu sınıfların nasıl kullanılabileceğinide örneklemiş olduk.İstemci kodun doğrudan fabrika asıl fabrika sınıflarına erişmemesi için ReportGenerator sınıfını tanımladım.Bu sınıf aracılığıyla raporlamaya dair bir çok iş gereksinimi gerçekleştirebilirim.Tabi biraz method eklemeniz gerekebilir.Ayrıca bu sınıfın genişleyebileceğini düşündüğüm için statik bir sınıf olarak tanım yapmadım ve  çalışma zamanında tek bir instance nın olması için singleton olarak tasarladım.

Şimdi de örnek uygulamamızın sınıf diagramını görelim.

capture_2

İlişkili desenler

Bu desen Factory method deseni ile benzerlikler gösterir.Tek farkla bir fabrika sınıfı yerine birden fazla fabrika sınıfını barındıracak soyut bir sınıf yaratılır.Bu desen fabrikaların fabrikası olarak da isimlendirilir.

Şimdilik bu kadar.Yazıda yanlış olduğunu düşündüğünüz yerleri lütfen yorumlayın 😀

Leave a Reply

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