참고 포스팅
해당 패턴의 출처는 Joshua Bloch에 의해 'Effective Java' 내에서 언급된 패턴입니다.
public class ResponseCode {
private int status;
private String code;
private String message;
public ExmpleCode(int status) {
this(status, null, null);
}
public ExmpleCode(int status, String code) {
this(status, code, null);
}
public ExmpleCode(int status, String code, String message) {
this.status = status;
this.code = code;
this.message = message;
}
}
쉽게 설명하면, 초기화할 필드 갯수만큼 생성자에 매개변수를 구성하는 패턴을 말합니다. 이를 통해서, 객체를 생성하고 싶을 때에는 정의한 매개변수를 필수로 넣어줘야만 하도록 할 수 있습니다.
이는 별도의 생성자를 구현하지 않고, 기본 생성자로 객체를 생성해준 뒤 setter를 사용하여 객체를 구성하는 형태를 말합니다.
public class ExampleCode {
private int status;
private String code;
private String message;
public void setStatus(int status) {
this.status = status;
}
public void setCode(String code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
}
위처럼 setter를 정의한 뒤, 기본 생성자로 객체를 생성하여 setter로 값을 초기화 해줍니다.
복잡한 객체의 생성 과정을 단계별로 분리하여 구현하는 생성 디자인 패턴을 의미합니다.
// GPT 작성 예시 코드
public class ExampleCode {
private final int status;
private final String code;
private final String message;
private ExampleCode(Builder builder) {
this.status = builder.status;
this.code = builder.code;
this.message = builder.message;
}
public int getStatus() {
return status;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public static class Builder {
private int status;
private String code;
private String message;
public Builder() {}
public Builder status(int status) {
this.status = status;
return this;
}
public Builder code(String code) {
this.code = code;
return this;
}
public Builder message(String message) {
this.message = message;
return this;
}
public ExampleCode build() {
return new ExampleCode(this);
}
}
💡 추가 설명
@NoArgsConstructor(access = AccessLevel.PROTECTED)
- 파라미터가 없는 생성자를 생성해주는 어노테이션을 의미하며, 무분별한 객체 생성에 대해서 한번더 체크하기 위한 수단을 의미합니다.
- AccessLevel.PROTECTED로 사용하는 이유는 Spring에서 프록시 객체 생성 시, PRIVATE로 제한되어 있게 되면, 생성이 불가능하기 때문입니다.
위처럼 자주 사용되는 생성자 패턴으로 3가지 정도가 있는데, 이 중 사용하기에 권장하는 방식은 Builder 방식입니다.
정층적 패턴은 생성자 호출 시, 매개변수의 순서가 다르게 입력될 수 있는 문제가 발생합니다.
public class ExampleCode {
private int status;
private String code;
private String message;
public ExampleCode(int status, String code, String message){
this.status = status;
this.code = code;
this.message = message;
}
}
위처럼 생성자가 정의되어 있을 경우, 생성자 호출 시 code와 message는 순서에 구분되어 값이 입력됩니다.
만약, 다음과 같이 순서를 바꾸어 입력해주게 된다면, 의도하지 않은 결과를 출력하게 될 수 있습니다.
이와 다르게, 빌더 패턴을 사용하게될 경우, 매개변수에 정확한 이름이 함께 구분되므로, 실수할 확률이 적어집니다.
// Builder Pattern 사용
Example exampleCode = Example.builder()
.status(200)
.message("성공 되었습니다.")
.code("200")
.build();
자바 빈즈 패턴은 객체에 setter로 모든 값을 세팅해주어야하기 때문에, 하나의 값을 실수로 빼먹고 set을 해주지 않게되면, 의도치 않게 null 값이 반환될 수 있습니다.
상대적으로 빌더패턴은 해당 필드명을 그대로 가져와 값을 입력하기 때문에, 가독성이 좋고 실수할 확률이 줄어듭니다.
이러한 이유로 인해서 Builder 패턴을 사용하는 것을 권장드립니다.