Spring Boot를 공부하면서 builder pattern을 처음 접하게 되었다. builder pattern에 대해 알아보기 위해 공부 목적으로 작성합니다.
간단한 builder 코드를 보겠습니다.
Board board = Board.build()
.title("GoodEvening World")
.author("Jack")
.build();
builder pattern에 대해 모르고 위 코드를 봤을 경우에도 대충 어떤 느낌인지 알 수 있습니다. setter 와 비슷한 느낌이라고 할까요? name에 값을 넣어주고, age에 값을 넣어주고... builder pattern 개념에 대해서 알아보죠.
builder pattern 코드만 봤을 경우 장점과 코드의 효율성을 파악하기 쉽지 않기 때문에 점층적 생성자 패턴과 자바빈 패턴 코드를 같이 보면서 builder pattern 이해를 높여 보겠습니다.
매개변수 개수만큼 생성자를 늘리는 방식이다. 1개의 인자를 받는 생성자도 만들 수 있고, 2개 혹은 전체 인자를 받는 생성자를 만들어도 된다.
// 점층적 생성자 패턴 코드의 예 : 회원가입 관련 코드
public class Member {
private final String name; // 필수 인자
private final String location; // 선택적 인자
private final String hobby; // 선택적 인자
// 필수 생성자
public Member(String name) {
this(name, "출신지역 비공개", "취미 비공개");
}
// 1 개의 선택적 인자를 받는 생성자
public Member(String name, String location) {
this(name, location, "취미 비공개");
}
// 모든 선택적 인자를 다 받는 생성자
public Member(String name, String location, String hobby) {
this.name = name;
this.location = location;
this.hobby = hobby;
}
}
new Member("Manning","LA","football") 같은 호출이 빈번하게 일어난다면, new Member("Manning") 으로 대체 할 수 있다.
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 3, 35, 27);
NutritionFacts pepsiCola = new NutritionFacts(220, 10, 110, 4, 30);
NutritionFacts mountainDew = new NutritionFacts(230, 10);
점층적 생성자 패턴의 인자 수가 늘어나면 코드를 파악하는게 어려웠다. 이를 해결하기 위한 방법 중 하나로 자바빈 패턴을 쓴다.
자바빈 패턴은 생성자에 전달되는 인자 수가 많을 때 적용 한다. setter 메소드를 이용하는 것이다.
public class CafeMenu {
private int coffee = 1; //필수
private int beverage = 1; //필수
private int dessert = 0; //선택
private int bakery = 0; //선택
private int drinks = 0; //선택
public CafeMenu(){}
//setter
public void setCoffee(int coffee) {
this.coffee = coffee;
}
public void setBeverage(int beverage) {
this.beverage = beverage;
}
public void setDessert(int dessert) {
this.dessert = dessert;
}
public void setBakery(int bakery) {
this.bakery = bakery;
}
public void setDrinks(int drinks) {
this.drinks = drinks;
}
}
CafeMenu starbucks = new CafeMenu();
starbucks.setCoffee(10);
starbucks.setBeverage(30);
starbucks.setDessert(10);
starbucks.setBakery(20);
starbucks.setDrinks(5);
학원 교육을 받았을때 가장 많이쓰고 이거 밖에 몰랐는데 이게 자바빈 패턴이였는지도 모르고 쓰고 있었다.
이제 Builder Pattern을 코드로 보고 어떤 장점과 단점이 있는지 알아보자.
public class CafeMenu {
private final int coffee;
private final int beverage;
private final int dessert;
private final int bakery;
private final int drinks;
public static class Builder {
// Required parameters(필수 인자)
private final int coffee;
private final int beverage;
// Optional parameters - initialized to default values(선택적 인자는 기본값으로 초기화)
private int dessert = 0;
private int bakery = 0;
private int drinks = 0;
public Builder(int cofee, int beverage) {
this.coffee = coffee;
this.beverage = beverage;
}
public Builder dessert(int val) {
dessert = val;
return this; // 이렇게 하면 . 으로 체인을 이어갈 수 있다.
}
public Builder bakery(int val) {
bakery = val;
return this;
}
public Builder drinks(int val) {
drinks = val;
return this;
}
public NutritionFacts build() {
return new CafeMenu(this);
}
}
private CafeMenu(Builder builder) {
coffee = builder.coffee;
beverage = builder.beverage;
dessert = builder.dessert;
bakery = builder.bakery;
drinks = builder.drinks;
}
}
위와 같이 만들어주면 다음과 같이 객체를 생성할 수 있다.
CafeMenu.Builder builder = new CafeMenu.Builder(2 , 2);
builder.dessert(1);
builder.bakery(1);
builder.drinks(2);
CafeMenu menu1 = builder.build();
혹은 아래와 같이 체인도 가능하다.
CafeMenu menu1 = new CafeMenu
.Builder(2,2)
.dessert(1)
.baker(1)
.drink(2)
.build(); //build()가 객체를 생성해 돌려준다.