Builder 패턴이란?
빌더 패턴은 생성자에 들어갈 매개 변수가 많든 적든 차례차례 매개 변수를 받아들이고
모든 매개 변수를 받은 뒤에 이 변수들을 통합해서 한 번에 사용을 합니다.
Builder 패턴의 장점
- 필요한 데이터만 설정
- 유연성 확보
- 가독성을 높임
- 불변성 확보
Builder 패턴을 쓰는 이유
/**
* 제약사항 : 이 객체는 한번 생성되면 읽기(Read)만 가능해야 합니다.
*/
public class PersonInfo {
private String name;
private Integer age;
private String favoriteColor;
private String favoriteAnimal;
private Integer favoriteNumber;
public PersonInfo(String name, Integer age, String favoriteColor, String favoriteAnimal, Integer favoriteNumber){
this.name = name;
this.age = age;
this.favoriteColor = favoriteColor;
this.favoriteAnimal = favoriteAnimal;
this.favoriteNumber = favoriteNumber;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public String getFavoriteColor() {
return favoriteColor;
}
public String getFavoriteAnimal() {
return favoriteAnimal;
}
public Integer getFavoriteNumber() {
return favoriteNumber;
}
public String getPersonInfo(){
String personInfo = String.format("name:%s, age:%d, favoriteColor:%s, favoriteAnimal:%s, favoriteNumber:%d"
, name, age, favoriteColor, favoriteAnimal, favoriteNumber);
return personInfo;
}
}
이 클래스는 한 사람의 정보를 담기 위한 것입니다. 하지만 제약 사항이 걸려 있습니다. 따라서 setter 메소드는 존재할 수 없고 오로지 생성자를 통해서만 데이터를 입력 받는다는 가정으로 만든 클래스입니다. 생성자를 보면 모든 매개변수를 받도록 하고 있습니다. 하지만 어떤 사람들은 모든 데이터가 없을 수도 있습니다. 예를 들어 "이름"과 "나이"만 알고 있는 사람의 경우는 다음처럼 객체를 만들어 내야 할 것입니다.
new PersonInfo("JDM", 20, null, null, null);
하지만 이경우는 가독성이 안좋겠죠. 그래서 추가 생성자를 만들어서 처리하도록 해봅시다. 다음과 같은 생성자가 추가될 겁니다.
public PersonInfo(String name, Integer age){
this(name, age, null, null, null);
}
이렇게 해서 하나의 케이스에 대해서는 처리를 했습니다. 하지만 여기에 새로운 유형의 정보가 들어온다면 어떻게 될까요?
예를 들자면, 이름만 있다거나, 이름과 좋아하는 동물만 있다거나 하면서요. 그럼 그때마다 새로운 생성자를 만들어 줘야 할까요?
문제는 하나 더 있습니다. 만약 데이터를 입력하는 순서가 달라진다면 그것도 큰 문제가 될겁니다.
// 이름이 들어가야할 곳에 좋아하는 동물이 들어갔습니다.
// 반대로 좋아하는 동물이 들어가야 할 곳에 사람 이름이 들어갔네요.
new PersonInfo("cat", 20, "JDM", null, null);
이런 경우 찾아내기도 힘들뿐더러 매번 사용자가 체크를 해야하는 상황이 옵니다.
그래서 불편함을 해소하고자 쓰는 패턴이 Builder 패턴입니다.
Builder 패턴 예제
Builder 패턴을 사용하기전에 아래의 3가지를 고려해야합니다.
- 불필요한 생성자를 만들지 않고 객체를 만든다.
- 데이터의 순서에 상관 없이 객체를 만들어 낸다.
- 사용자가 봤을때 명시적이고 이해할 수 있어야 한다.
그래서 다음과 같은 빌더 패턴을 적용한 Builder 클래스가 필요합니다.
@Getter
public class PersonInfoBuilder {
private String name;
private Integer age;
private String favoriteColor;
private String favoriteAnimal;
private Integer favoriteNumber;
public PersonInfoBuilder setName(String name) {
this.name = name;
return this;
}
public PersonInfoBuilder setAge(Integer age) {
this.age = age;
return this;
}
public PersonInfoBuilder setFavoriteColor(String favoriteColor) {
this.favoriteColor = favoriteColor;
return this;
}
public PersonInfoBuilder setFavoriteAnimal(String favoriteAnimal) {
this.favoriteAnimal = favoriteAnimal;
return this;
}
public PersonInfoBuilder setFavoriteNumber(Integer favoriteNumber) {
this.favoriteNumber = favoriteNumber;
return this;
}
public PersonInfo build(){
PersonInfo personInfo = new PersonInfo(name, age, favoriteColor, favoriteAnimal, favoriteNumber);
return personInfo;
}
}
public class BuilderPattern {
public static void main(String[] args) {
// 빌더 객체를 하나 만듭니다.
PersonInfoBuilder personInfoBuilder = new PersonInfoBuilder();
// 빌더 객체에 원하는 데이터를 입력합니다. 순서는 상관 없습니다.
PersonInfo result = personInfoBuilder
.setName("MISTAKE")
.setAge(20)
.setFavoriteAnimal("cat")
.setFavoriteColor("black")
.setName("JDM") // 다시 같은 메소드를 호출한다면 나중에 호출한 값이 들어갑니다.
.setFavoriteNumber(7)
// 마지막에 .build() 메소드를 호출해서 최종적인 결과물을 만들어 반환합니다.
.build();
// print is "name:JDM, age:20, favoriteColor:black, favoriteAnimal:cat, favoriteNumber:7"
System.out.println(result.getPersonInfo());
}
}
사용자 입장에서 PersonInfo 객체를 만들어 낼 때 PersonInfoBuilder 클래스를 이용한다면 조금 더 명확하게 이해하고 만들어 낼 수 있을겁니다.
'CS (Computer Science)' 카테고리의 다른 글
[디자인 패턴] 싱글톤 패턴이란? (0) | 2022.09.28 |
---|