Builder Design Pattern

Builder Design Pattern

Merhaba sevgili dostlar; tasarım desenleri makale serimize Builder Design Pattern ile devam ediyoruz.

Bu arada tabii, bir önceki yazıdan yalnızca bir hafta sonra makale yazmam beni de çok şaşırtıyor elbette. Aman diyeyim tahtaya vurun da nazar değmesin. Her neyse. Konsantrasyonumuzu bozmadan konumuza dönüp muhabbetimize devam edelim.

Efendim; Builder Design Pattern de yaratımsal tasarım desenleri (Creational Design Patterns) kategorisinde yer alan desenlerden biri. Haliyle kendisi yine, bir nesne yaratma problemini çözmek üzere karşımıza çıkıyor.

Şimdiye dek her desende yaptığım gibi, bu desende de önce problemi anlamaya çalışalım dilerseniz. Uygulamanızda kullanacağınız nesneniz oldukça fazla özelliğe sahipse ve bu özellikleri farklı kombinasyonlarda kullanmanız gerekirse, nasıl bir nesne oluşturma yöntemi izlemeliyiz? Bir nesne, ilgili class’ın Constructor’ u sayesinde elde edildiğine göre aklımıza ilk gelen Constructor üyesini her ihtiyacımız için yeniden yazma (overload etme) yöntemi olabilir.

Ancak bu yöntemi uygularsanız, onlarca hatta belki de daha fazla Constructor üyesi eklemiş olursunuz class’ a. Bu da hangi Constructor’ un ne zaman kullanılacağı gibi kâbus bir soruyu beraberinde getirecektir. İşte sorun tam olarak bu! Birkaç parçadan oluşan karmaşık bir nesneyi, Constructor kargaşasına girmeden nasıl çözeriz?

Hadi, günlük hayatımızda bu sorunu nasıl çözdüğümüze bir bakalım. Öncelikle, birkaç parçadan oluşan bir nesne bulalım kendimize… Hımm… Bilgisayara ne dersiniz mesela? Ana kart, RAM, Hard Disk, CPU vs. gibi parçalardan oluşan bir nesnedir bilgisayar. Elinizde bir dizüstü de olsa, masaüstü de olsa bu parçalar olmak zorunda. Şimdi şöyle bir robot düşünün: gerekli parçaları ürettikten sonra onları sırasıyla, adım adım montajlayarak bilgisayar üreten bir robot. Efendim? Bu sorunumuzu çözer miydi?

Yani, karmaşık bir nesneyi oluşturan parçaları üretip sonra da onları adım adım birleştiren bir üretici nesne yapabilirsek, biz de yazılımsal problemimizi çözebiliyoruz sanırım.

Hadi şimdi de yazılımsal bir senaryo üzerinden gidelim. Şimdi efenim, uygulamanızın üye kullanıcılara belirli dönemlerde çeşitli mesajlar atmasına gereksinim duyuyorsunuz. Her mesaj için bir HTML şablonu hazırladınız. Sadece gerekli alanları doldurup mesajı oluşturmanız gerekiyor. Gelin bu senaryoda Builder Design Pattern’i nasıl kullanacağımıza bir bakalım.

Öncelikle, uygulamamın göndereceği mesaj tiplerini tutmak üzere bir enum tipi tanımlıyorum.

Bir mesaj, tipten bağımsız olarak üç parçadan oluşuyor. Bunlar; başlık, içerik ve imza kısımları. O halde mesaj class’ ını bu özelliklerden oluşturacağım. Fakat bu üç parçanın da değeri, mesajın tipine göre değişkenlik gösterecektir. Bunu da dikkate alarak Mesaj class’ını aşağıdaki gibi tasarlıyorum:

Buradaki Mesaj sınıfı, günlük hayat örneğimizdeki Bilgisayar sınıfı (Product). Yani işlem bittiğinde oluşacak karmaşık nesnemiz. Şimdi, parçaları bir araya getirecek bir birleştirici sınıfa ihtiyacımız var. Senaryomuzda birden fazla Mesaj tipimiz olduğunu belirtmiştik (enum), mesajın parçaları bu tiplerden bağımsız, fakat parçaların değeri kesinlikle tipe bağımlı. O halde, birleştirici sınıfım abstract olmalı.

Burada dikkatlerden kaçmaması gereken çok önemli bir nokta var! MesajBuilder class’ ı, 55. Satırda Mesaj nesnesi döndürüyor. E bu normal değil mi? Parçaları birleştir ve mesajı döndür diyoruz işte.

Şimdi, enum tipi içerisinde belirttiğim birkaç mesaj tipine özel sınıflar oluşturalım. Bu sınıflar günlük hayat örneğimizdeki, dizüstü ya da masaüstü bilgisayarları üreten robotlar gibi oluyor.



Gördüğünüz gibi, DogumGunuTebrikBuilder class’ı abstract MesajBuilder class’ını miras alıyor ve bu nedenle de mesajı oluşturan parçaları özelleştirmesi gerekiyor. Ayrıca, Constructor üyesi içinde, hangi mesaj tipine göre değer yaratacağını söylediğimize dikkat çekmek isterim.

Aynı miras stratejisi ile MesajTipi enum’ u içerisinde belirttiğim her tip için bir sınıf üretmem gerekiyor. Tabii ki ben bu makaleyi kısa tutmak ve aynı şeyleri tekrar etmemek için, sadece bir class daha geliştireceğim.

Şimdi, elimizde iki adet birleştirici sınıf (robot) var. Peki, bu sınıflardan hangisini seçeceğiz? Biz niye seçelim ki? Sonuçta her birleştirici sınıf MesajBuilder abstract class’ını miras alıyor. O zaman buna göre bir üretici class yazabiliriz.

İşte önemli noktalardan biri daha MesajUretici class’ının Uret(MesajBuilder builder) metodunu inceler misiniz? Adım adım birleştirme işini yapıyor ve sırası kesinlikle bozulmayacak şekilde düzenlenmiş. Ayrıca Goster() metodu da mesajın tamamlanmış halini çalıştırıyor.

O halde benim bir mesaj nesnesine ihtiyacım olduğunda yapacağım şey; MesajUretici sınıfının Uret metodunu, gerekli parametreyle çağırmak olacak. Hadi deneyelim öyleyse…

Eh ekran çıktısını görmeden inanmam diyorsanız bakalım o zaman:

İşte gördüğünüz üzere; karmaşık bir nesneyi, Constructor kaosuna düşmeden builder tasarım deseni kullanarak adım adım birleştirerek oluşturduk.

Böylece, bir deseni de tarihe gömmüş oluyoruz sevgili object oriented severler.

Bir dahaki yazıya dek, kalın sağlıcakla…

3 thoughts on “Builder Design Pattern

  1. Türkay Bey Gayet güzel bir paylaşım olmuş. Tekrar detaylı olarak inceledikten sonra size sorularım olacak. Ha bu arada paylaşımlarınızı ilgiyle takip ediyorum. Lütfen makalelerinize uzun aralar vermeyin. Yarlı olduğunuz baya bir insan var. üstelik evli ve şişman çoğunlukta.

  2. son derece başarılı bir yazı dizisi. Enterprise integration patterns ile de ilgili bir yazı dizisi düşünür müydünüz?

  3. Merhaba. İnternette araştırdığımda bulduklarımdan biraz farklı anlatmışsınız. Orda genellikle Fluent API yaklaşımı ile kullanıyorlar bu tasarım kalıbını. Neyse, benim kafamı karıştıran noktayı söyleyeyim. Yine internetten araştırdığıma göre bu tasarım kalıbı factory ve abstract factory tasarım kalıpları yerine kullanılıyormuş. Hatta genelde yazılımcılar factory ile başlıyor muş sonra abstract factory’e geçiyormuş sonrada builder geçmek zorunda kalıyormuş gibi bir söylem var. Anlamadığım şey abstract factory tasarımın daha gevşek bağlı(loosly coupled) olmasını sağlamıyor mu?. Abstract factory’i DI container aracılığıyla register edip kullanabiliyoruz. Builder kullanınca new deyip nesne yaratmak durumunda kalıyoruz. Bu yazdığımız kodu sıkı bağlı(tightly coupled) yapmaz mı? Yaparsa eğer neden abstract factory den builder’a geçeyim ki?

    Teşekkürler.

Leave a Reply