Tasarım Örüntüleri
Builder Pattern
Creational Patterns bir örneği olan Builder Pattern bize kompleks nesneleri oluşturmakta zorlandığımız durumlarda nasıl bu işlemi kolaylaştırabileceğimiz konusunda bir yaklaşım sunar.
Bilgi Notu: Diğer tüm Tasarım Örüntüleri yazıma bu linkten ulaşabilirsiniz.
Hangi Durumda
Aşağıdaki sınıfı incelediğimizde 4 tane özelliği bulunuyor. Bunlar x,y,width, height. 4 tane özelliği bu nesnenin anlamlı olması için gerekli. Bu durumda bu nesne için 1 tane constructor yeterli olacaktır.
class Rect
public Rect(int x, int y, int width,int height) //Constructor
Bu tarz Rect gibi oluşturulması basit yani 1,2 constructor oluşturarak nesneyi oluşturabiliyorsanız bunlara oluşturulması basit nesneler diyebiliriz.
Ama bazı nesneler vardır ki bunların çok fazla parametresi bulunur. Ve bunlardan x1,x3 ile başka nesne görünümü oluşturulurken, x4,x5 ile başka bir nesne görüntüsü oluşturulabilir durumların sayısı çok arttığında tüm kombinasyonları karşılayacak bir constructor oluşturmak oldukça zor olur.
class Complex
int x1,x2,x3,x4 ...................
constructor1(x1, x2)
constructor2(x3, x4)
constructor3(x5, x1)
.....
Örneğin bir SQL cümlesi oluşturacaksınız Select her zaman olacak ama Where olmak durumunda değil, GroupBy olmak durumunda değil vb…
Örneğin bir yemek sipariş nesneniz var. İstenilen yemek parçalarına göre Hamburger, Patates, Kola olsun veya yanında İçecek olmasın gibi nesnenizin farklı farkı görüntüleri olabilir
Bu durumda bir diğer yöntem boş/default constructor ile sınıfı oluşturup bu nesneye set veya add gibi metodlar ile oluşturabilirsiniz.
class Complex
setX1()
setX2()
setX3()
setX4()
Bu durumda sınıfınız bir çok set metodu oluşacaktır. Örneğin bir Sipariş bilgisini aşağıdaki şekilde yazalım.
//Sipariş Oluşturma işlemi
Order order=new Order();
order.addHamburger(type, count)
order.addDrink(type, count)
order.addPizza(type, count)
......
Burada kodu yazarken sipariş oluşturma işi bir bütün olarak gözükmez. Çünkü geliştirici arada başka başka işlemlerde yapabilir
//Sipariş Oluşturma işlemi
Order order=new Order();
order.addHamburger(type, count)
order.addDrink(type, count)
sum = 3+2;
callFunction()
order.addPizza(type, count)
......
Avantajları
Ama bunu Builder Pattern ile yazdığımızda her kendi basit DSL(Domain Specific Language) oluşturacak this döneceği için daha odaklı bir nesne oluşturma yapısı oluşturabiliriz.
Nested Builder
new Order.Builder().hamburger(ABurger,2).drink(BDrink,1).build()
Peki bunu nasıl gerçekleştireceğiz. Kompleks nesnemizin içerisine bunun üretilmesinden sorumlu bir Builder objesi olacak bu bizim Burada kompleks nesne oluşturma mantığını nesnenin kendi kendi içerisindeki bulunan Builder
public class Order
ArrayList<Enum,int> hamburgers
ArrayList<Enum,int> drinks
ArrayList<Enum,int> pizza public static class OrderBuilder
//return this
public OrderBuilder hamburger(type, count){}
public OrderBuilder drink(type, count){}
public OrderBuilder pizza(type, count){} //return Order
public buid(){ return new Order()..}
Not: Burada Order default constructor private hale getirmek , set metodlarını dışarıya kapatmak bu kompleks nesnenin olabildiğince kontrollü oluşmasını sağlayacaktır.
Builder Pattern Yapısı
Diğer bir yöntemde Product türünü oluşturabilecek ara Builder interface gerçekleştirmiş sınıflar farklı türdeki nesneleri oluşturma adımlarını kendi içlerinde saklar ve buna göre oluştururlar.
Örneğin aşağıda Araba nesneleri oluşturmak isteyelim. Ferrari, Opel, Mercedes, BMW, WV vb.. türlerde oluşturmak.
Car : Arabamızın Markası, Modeli, KapıSayısı ve Rengi var.
ICarBuilder : Araç oluşturma arayüzü Renk ve Araç Kapısını değişken olarak alıyor
FerrariBuilder : Aracın Markası, Modeli zaten bu sınıf biliyor. Burda bir takım kendi sınıfına özel koşullarıda içeriyor olabilir örneğin Kapı sayısı limitleri vardır set ettirmez gibi … Ve biz BMWBuilder, MercedesBuilder vb.. bu sınıfları arttırabiliriz.
SportsCarBuildDirector: Kendisine gelen araçlara belki bir servisten aldığı , belki kullanıcı arayüzünden aldığı Renk ve Kapı sayısı değerini set etmekten sorumludur.
Client : Tüm bu süreci yöneten sınıf.
Değişiklik İhtiyaçlarını Nasıl Karşılayacak
- Yeni bir Araç türü geldiğinde bu yapıyı değiştirmeden tek bir sınıf ekleyerek bu yapımızı genişletebiliriz.
- İlgili araç özelinde bir kısıtlama geldiğinde ortak yapıyı etkilemeyen bir konu ise sadece ilgili sınıfta mantığı değiştirerek sorunu çözebiliriz.
- Eğer Ortak bir yapıda değişiklik var ise bunun Tüm arayüzlerde değişikliğini bileceğiz ve tüm sistem sınıflarında güncelleme yaparak eksik bir nokta bırakmayı engeller.
Referanslar
Okumaya Devam Et 😃
Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.