[Java] 생성자 패턴 이해하기

Kim Hyen Su·2024년 9월 4일
0

📐Java

목록 보기
16/18
post-thumbnail

참고 포스팅

생성자 패턴의 종류

1. 점층적 생성자 패턴(Telescoping Constructor Pattern)

해당 패턴의 출처는 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;
    }
}

쉽게 설명하면, 초기화할 필드 갯수만큼 생성자에 매개변수를 구성하는 패턴을 말합니다. 이를 통해서, 객체를 생성하고 싶을 때에는 정의한 매개변수를 필수로 넣어줘야만 하도록 할 수 있습니다.

2. 자바 빈즈 패턴(Java Beans Pattern)

이는 별도의 생성자를 구현하지 않고, 기본 생성자로 객체를 생성해준 뒤 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로 값을 초기화 해줍니다.

3. 빌더 패턴(Builder Pattern)

복잡한 객체의 생성 과정을 단계별로 분리하여 구현하는 생성 디자인 패턴을 의미합니다.

// 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 방식입니다.

Builder Pattern을 사용해야 하는 이유

1. 생성자 호출 시, 매개변수의 순서를 잘못입력하는 경우를 없앤다.

정층적 패턴은 생성자 호출 시, 매개변수의 순서가 다르게 입력될 수 있는 문제가 발생합니다.

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();

2. 가독성이 좋아집니다.

자바 빈즈 패턴은 객체에 setter로 모든 값을 세팅해주어야하기 때문에, 하나의 값을 실수로 빼먹고 set을 해주지 않게되면, 의도치 않게 null 값이 반환될 수 있습니다.

상대적으로 빌더패턴은 해당 필드명을 그대로 가져와 값을 입력하기 때문에, 가독성이 좋고 실수할 확률이 줄어듭니다.


이러한 이유로 인해서 Builder 패턴을 사용하는 것을 권장드립니다.

profile
백엔드 서버 엔지니어

0개의 댓글