Design pattern'leri spagetti kodlara veya tekrar eden kod bloklarına çözümler olarak ortaya çıkmışlardı. Builder Design Pattern creational patterns kategorisi altında bulunan patternlerden birisidir ve kısaca basit objeler kullanarak complex objeler inşa etmede kullanılır diyebiliriz.
Builder'ı DTO yani data transfer object class'larını örnek olarak düşünürsek, bu objeler birden fazla objenin birleşmesinden oluşurlar ve genelde complex objelerdir. Builder pattern'nini de base'de bir obje var ve bu objeye ait alt property'leri oluştururken her bir özellik için ayrı build metotları yazmamız gerekir. Builder design pattern'i bu gibi durumlarda kullanabilecegimiz bir pattern olarak dusunebiliriz. Başka bir deyişle; runtime da yaratılması gereken complex objelerinizin olduğu bir projeniz varsa bu pattern'i kullanmak güzel bir seçim olabilir veya adım adım obje yaratma işlemlerini yönetmek istediğiniz bir durum var ise yine bu pattern'i kullanabiliriz.
Builder pattern'i 4 ana yapıdan oluşur;
- Product : Build edilen obje,
- Builder : Product'ı build eden abstract yapı,
- Concrete Builder : Builder nesnesinin abstract yapıyı kullanarak aynı yapıdaki farklı ürünlerin build edilmesini sağlayan yapı,
- Director : Kendisine verilen Builder'ı property'lerini kullanarak ürünü inşa eden yapı.
Örnek bir proje üzerinden Builder Design Pattern'i implement etmeye çalışalım. Apple fabrikasında Iphone modelleri üretimi yapan bir senaryo yazalım ve bunu pattern'imizi uygulayarak yapmaya çalışalım.
Öncelikle ürün class'ımızı oluşturalım. Iphone'un farklı modellerini (6, 6S, SE, vs.) ürettiğimizi düşünelim ve constractor seviyesinde hangi modeli ürettiğimiz bilgisini verelim.
//Product'ımız
public class Iphone
{
string phoneType;
public Iphone(string phoneType)
{
this.phoneType = phoneType;
}
}
Şimdi ise Builder gibi davranan abstract class'ımızı oluşturalım. Bu class üretimde kullanacağımız abstract üyeler içerecektir. Icerisinde BuildOS ve BuildDevice adında iki abstract metot ve hangi iphone modelini üreteceği bilgisinin olacağı Iphone tipinde olan obje olacaktır.
//abstract Builder nesnemiz
public abstract class IphoneBuilder
{
public abstract void BuildOS();
public abstract void BuildDevice();
Iphone IphoneType { get; }
}
Sırada Builder class'larını geliştirme var. 6sBuilder ve SeBuilder adında iki tane iphone modeli için geliştirme yapalım.
SeBuilder
// SE modeli için kullanacağımız Concrete Builder class'ımız
public class SeBuilder : IphoneBuilder
{
Iphone device;
public SeBuilder()
{
device = new Iphone("Se");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Iphone IphoneType
{
get { return device; }
}
}
_6sBuilder
// 6S modeli için kullanacağımız Concrete Builder class'ımız
public class _6SBuilder : IphoneBuilder
{
Iphone device;
public _6SBuilder()
{
device = new Iphone("6S");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Iphone IphoneType
{
get { return device; }
}
}
Şimdi sırada üretim var. Manufacturer adında üretici class'ımızı oluşturalım.
//Director class'ımız
public class Manufacturer
{
public void Build(IphoneBuilder iphoneBuilder)
{
iphoneBuilder.BuildDevice();
iphoneBuilder.BuildOS();
}
}
Sıra yaptığımız implementasyonu kullanmaya geldi.
public static void Main()
{
Manufacturer manufacturer = new Manufacturer();
_6SBuilder _6s = new _6SBuilder();
manufacturer.Build(_6s);
}
Main fonksiyon içerisinde Manufacturer'ı kullanarak _6s modelini build ettik. Builder pattern'nini elimizden geldiğince projemize entegre ettik ve diğer iphone ürünleri için de aynı akışı kullanarak ürünlerimizi Build edebiliriz.
Builder pattern'i factory ve abstract factory pattern'leri ile birçok yönden benzerlikler göstermektedir. Hangisini kullanmalıyım diye tereddütte kaldığınız durumlarda, complex objeler yaratıyorsanız Builder'ı, tek bir obje yaratmak istiyorsanız da factory veya abstract factory design pattern'i tercih edebilirsiniz.