클라이언트에서 넘겨받은 데이터를 담을 PostDTO 클래스가 있다고 하자. 근데 처음에는 이름, 나이, 도시 정보만 넘겨주면 됐었는데 국가, 취미 등의 정보도 추가되어야 한다고 해보자.
1번의 경우 모든 생성자를 만들게 되면 멤버변수가 증가하거나, 필수적으로 필요한 매개변수값이 있는 경우 등등... 모든 경우의 생성자를 다 생성해줘야 한다. 또한 다음과 같은 문제도 있을 수 있다.만약 생성자의 매개변수 순서와 다르게 객체를 생성해버리면 문제가 당연히 생기겠죠?
2번의 경우를 생각해보면 setter의 존재로 인해서 협업을 할 때 값이 여러곳에서 변경이 발생할 수 있고 이로인해서 유지보수 난이도가 올라간다는 문제가 있다.
public class PostDTO {
private String name;
private Integer age;
private String city;
public PostDTO(String name , String city , Integer age) {
this.name = name;
this.city = city;
this.age = age;
}
}
-----------------------------------------------------------
//실제 객체를 생성할 떄
PostDTO postDTO = new PostDTO("서울", "baeksu", 30);
System.out.println("postDTO = " + postDTO);
-----------------------------------------------------------
그래서 등장한 것이 Builder 패턴이다!
PostDTO 내부에서만 사용하는 Builder 클래스를 통해서 이제 객체를 생성하게 할거다. 내가 객체를 생성할때 원하는 멤버변수만 set을 chaining 으로 값을 주입해준다. 이후에 Builder.builder() 를 하게 되면 PostDTO 객체에 값을 넣어주게 된다.
이런식으로 객체를 생성하면 변경에도 유연하게 대응할 수도 있고 개발자가 개발하다가 매개변수의 순서 실수도 방지할 수 있다. 또한 PostDTO 에 setter 가 직접있는게 아니라서 무분별한 변경도 방어할 수 있어서 좋은듯
public class PostDTO {
private String name;
private Integer age;
private String city;
public PostDTO(String name , String city , Integer age) {
}
public static class Builder{
private String name;
private Integer age;
private String city;
public PostDTO build(){
PostDTO postDTO = new PostDTO();
postDTO.name = name;
postDTO.age = age;
postDTO.city = city;
return postDTO;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(Integer age) {
this.age = age;
return this;
}
public Builder setCity(String city) {
this.city = city;
return this;
}
}
@Override
public String toString() {
return "PostDTO{" +
"name='" + name + '\'' +
", age=" + age +
", city='" + city + '\'' +
'}';
}
}