Java

Builder패턴을 사용하는 이유

chandlerxx 2024. 1. 10. 16:53

결론입니다.

Builer패턴을 사용하는 이유

1. 객체의 불변성
2. 어떤 값을 채워줘야하는지 명확합니다.

 

1. 생성자의 매개변수가 많을때는 Builer패턴을 사용하는 편이 좋습니다


 

코드를 통해 확인해보겠습니다. (디테일한 내용은 여기를 참고해주세요)  

 

Area를 구하는 객체 클래스를 생성했고, 조건은 아래와 같습니다.

  • 필수 필드 : width, height
  • 옵션 필드 : margin, padding 
package com.chandler.webservice.area;

public class Area {

    private int width;
    private int height;
    private int margin;
    private String padding;

    public Area(int width, int height) {
        this(width, height, 0, "abc");
    }

    public Area(int width, int height, int margin) {
        this(width, height, margin, "abc");
    }

    public Area(int width, int height, String padding) {
        this(width, height,0, padding);
    }

    public Area(int width, int height, int margin, String padding) {
        this.width = width;
        this.height = height;
        this.margin = margin;
        this.padding = padding;
    }


}

 

 

그리고 Area를 구하기 위해 AreaApp 클래스를 생성하여, 객체를 생성해보았습니다.

여기서 `문제점`이 보입니다.

  • 가독성이 좋지 못합니다.
  • 개발자의 실수로 인해 의도치 않은 오류가 발생할 가능성이 높습니다.
    ㄴ margin까지만 입력한 인스턴스를 생성해야 하는데, padding 매개변수까지 입력할 경우, 최초 의도했던 area1이 아닌 area2 객체가 생성될 수 있습니다.
  • 코드는 명확해야 합니다.
    ㄴ 코드만 보면 중요한 필드는 무엇이고, 어떤 필드를 생성하여 주입해줘야하는지 명확하지 않습니다.

 

 

 

2. Builder 패턴 적용해보겠습니다


 

롬복 라이브러리의 `@Builder` 애노테이션을 이용합니다.

import lombok.Builder;

public class Area {

    private int width;
    private int height;
    private int margin;
    private String padding;

    @Builder
    public Area(int width, int height, int margin, String padding) {
        this.width = width;
        this.height = height;
        this.margin = margin;
        this.padding = padding;
    }
}

 

@Builder패턴을 사용하면 아래와 같은 장점이 있습니다.

 

  • 직관적입니다.
    ㄴ 필드로 어떤 값을 주입해야하는지 알 수 있습니다.
  • 원하는 필드값만 주입하여 인스턴스를 생성할 수 있습니다. 
  • `객체의 불변성`을 유지합니다.
    ㄴ 자바빈 규약에 의해 setter를 무분별하게 사용하는 것을 지양해야 합니다. setter에 의해 다른 클래스에서 생성된 객체들의 값이 바뀌게 된다면 유지보수 측면에서 원인 모를 에러 발생 가능성이 높습니다. 
    ㄴ @Builder로 구현할 경우, setter를 사용하지 않기에 불변성을 유지할 수 있습니다.