Builder Pattern Nedir ? @Builder @SuperBuilder Anotasyonları Nedir ?
Öncelikle merhabalar, bu yazımızda builder design pattern hakkında konuşacağız. Daha önceki design patternlar hakkındaki yazımı okumadıysanız buradan okuyabilirsiniz.
Önceki yazımızda da öğrendiğimiz gibi design patternlar, daha öncesinde karşılaşılan problemlere bulunan efektif, kullanışlı çözümler olarak tanımlıyorduk. Design patternların 3'e ayrıldığından bahsetmiştik. Bu yazımızda da bu 3 başlıktan ilki olan Creational Patterns (Yaratımsal Kalıplar)’lardan biri olan Builder patternden bahsedeceğiz.
Creational Patterns (Yaratımsal Desenler), Bu tasarım deseni nesneleri klasik olarak oluşturmak yerine nesne oluşturma mantığını gizleyerek sınıflardan nesne oluşturmaya alternatif çözümler sunar. Bu program akışında hangi nesneye ihtiyaç varsa onu oluşturmada esneklik ve kolaylık sağladığından bahsetmiştik. O halde builder pattern’e yakından bir göz atma vakti geldi.
Builder Pattern Nedir ?
Builder pattern, projelerimizdeki sınıflarımızda kullandığımız constructor sınıfları ile yeni nesneler üretirken constructorun fazla sayıda değişken içerdiği, karmaşıklıklara yol açtığı anlar için bizlere yeni alternatif bir yol sunuyor.
public class Car {
private String plate;
private String brand;
private String model;
private String color;
private String carType;
private double maxSpeed;
private double torque;
private int year;
public Car(String plate, String brand, String model, String color, String carType, double maxSpeed, double torque, int year) {
this.plate = plate;
this.brand = brand;
this.model = model;
this.color = color;
this.carType = carType;
this.maxSpeed = maxSpeed;
this.torque = torque;
this.year = year;
}
}
Yukarıdaki kod parçasında gördüğünüz üzere, bu şekilde bir araba sınıfımız olduğunda dışarıdan bir araba nesnesi oluşturmak istediğimiz zaman tek tek istenilen değerleri şu şekilde yerleştirmek gerekir.
public class Main {
public static void main(String[] args) {
Car car = new Car("34 ABC 12",
"BMW",
"i320",
"White",
"Sport",
300,
2000,
2020);
}
}
Bu tarz bir kod parçasında hata yapmadan tek tek yerleştirmek biraz zor ve karmaşık bir işlem. Bunun için bizler bu sorunu çözebilmek için builder patterne başvuruyoruz.
Builder Pattern’in Altında Yatan Mantık
Aslında temel mantık şu şekilde, pattern’ımızı kullanmak istediğimiz sınıfın içerisinde static bir builder sınıfı oluşturuyoruz. Aynı field(alanlar)’ları static olan builder sınıfımızda da oluşturup set ediyoruz. En son da bunlardan yeni bir nesne elde edebilmek için builder patterninden yararlanmak istediğimiz sınıfın içerisine builder parametresi alacak bir constructor oluşturarak static olan sınıfımızda build() isimli bir metot ile yeni nesnemizi oluşturuyoruz.
public class Car {
private String plate;
private String brand;
private String model;
private Car(Builder builder) {
this.plate = builder.plate;
this.brand = builder.brand;
this.model = builder.model;
}
public String getPlate() {
return plate;
}
public String getBrand() {
return brand;
}
public String getModel() {
return model;
}
public static class Builder {
private String plate;
private String brand;
private String model;
public Builder setPlate(String plate) {
this.plate = plate;
return this;
}
public Builder setBrand(String brand) {
this.brand = brand;
return this;
}
public Builder setModel(String model) {
this.model = model;
return this;
}
public Car build() {
return new Car(this);
}
}
}
Yukarıdaki gibi builder patternimizi oluşturduğumuzda artık yeni nesnelerimizi üretmek daha yönetilebilir ve daha rahat olacaktır. Şu şekilde yeni nesnelerimizi kolaylıkla oluşturabiliriz.
Car car = new Car.Builder()
.setPlate("34ABC123")
.setBrand("Ford")
.setModel("Mustang")
.build();
}
Buraya kadar pure Java ile anlatmaya çalıştım. Umarım sizler için yararlı olmuştur. Bu kısımdan sonraki kısımlarda ise Java’da lombok kütüphanesine dahil olan @Builder @SuperBuilder anotasyonlarını inceleyeceğiz.
@Builder Anotasyonu
Java’nın Lombok kütüphanesiyle birlikte gelen bu anotasyon yukarıdaki işlemleri bizler için otomatik bir hale getirerek hem az kod yazmamızı sağlıyor, hem de gerçekten bizlere zaman kazandırıyor. Kullanımı ise gerçekten çok basit. Sınıfı tanımının üzerine @Builder anotasyonu eklemeniz yeterli.
import lombok.Builder;
@Builder
public class Car {
private String plate;
private String brand;
private String model;
}
Çağırırken de şu şekilde yeni nesnemizi oluşturabiliriz.
Car car = Car.builder()
.plate("34ABC123")
.brand("Ford")
.model("Mustang")
.build();
@SuperBuilder Anotasyonu
Yine Java’nın Lombok kütüphanesiyle birlikte gelen bu anotasyon aslında @builder anotasyonundan farklı olarak sadece içerisinde bulunduğu sınıfın özelliklerini değil, içerisinde bulunduğu sınıfın özelliklerini ve üst sınıfının özelliklerini de dahil ediyor. Böylelikle ihtiyacınız olduğunda bu anotasyonu da kullanabilirsiniz. Sınıfı tanımının üzerine @SuperBuilder anotasyonu eklememiz yeterli.
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class Vehicle {
private String plate;
}
@Getter
@Setter
@SuperBuilder
public class Car extends Vehicle {
private String brand;
private String model;
}
Yeni metotumuzu oluştururken artık sadece istenilen sınıfın özelliklerine değil, üst sınıfın özelliklerine de doğrudan ulaşabiliyoruz.
Car car = Car.builder()
.plate("34ABC123")
.brand("Ford")
.model("Mustang")
.build();
Böylelikle bu yazımızın da sonunda geldik. Gerçekten çok kullanışlı bir design pattern. Bu yazıyla birlikte sizlerle birlikte ben de öğrenmiş oldum. Öğrendiklerimi de elimden geldiğince aktarmaya çalıştım. Umarım sizler için de faydalı bir yazı olmuştur. Sonraki yazılarımızda görüşmek üzere, sağlıcakla kalınız👋