Builder 패턴 사용 이유

김의진·2021년 10월 5일
0

Setter 사용의 지양

Partner partner = partnerDAO.selectPartnerInfoByPartnerId(request.getPartnerId());
        petSaleContract.setSalesLicense(partner.getSalesLicense());
        petSaleContract.setBizCompany(partner.getCompany());
        petSaleContract.setBizAddress(partner.getAddress());
        petSaleContract.setBizZipCode(partner.getZipCode());
        petSaleContract.setBizContact(partner.getContact());
        petSaleContract.setBizCeo(partner.getCeo());

개발을 하다 어느순간 객체 생성후 내부 변수 세팅을 위해서 setter메소드를 변수 갯수 만큼 호출하다 보니 과연 옳은 방법인가 의문이 들게 되었다.
나중에 알고보니 이런 방법을 자바빈즈 패턴이라고 부르더라..
몇가지 글을 읽다보니 Setter 사용을 지양해야한다는 글을 보게 되었고.(물론 상황에 따라 다름)
생성자 혹은 Builder 패턴을 사용하여 객체 필드값을 초기화 해줘야 함을 보게 되었다.

Setter의 사용을 지양해야하는 다양한 이유가 있겠지만 의도하지 않은 포인트에서 Setter의 사용으로
데이터가 변하게 되는걸 막고 이를 통해 생성된 객체를 불변객체로 유지시키는 것이 가장 큰 목적으로 보인다.

한가지 예로 ArrayList의 size는 getter만 있을뿐 setter가 없다. size의 값은 특정 필드에
종속적일뿐 해당 값을 일방적으로 수정해서는 안되기 때문으로 보인다.

그럼 Setter를 대신할 방법은 무엇일까?

생성자 사용

객체 생성시 생성자를 이용해서 해당 객체를 초기화 해주는 방법이다.

다만 생성자를 이용해서 객체 초기화시 단점이 한가지 있는데 매개변수에 따른 대응이 어렵다는 것이다.
A, B, C 매개변수가 있을때 A,B,C를 모두 초기화 해주는 경우도 있지만 A, C만 초기화 해줘야할 경우
새롭게 생성자를 만들어줘야한다. 상황에따라 계속해서 생성자를 만들다보면 코드가 혼잡해진다.
또한 매개변수가 많아질 경우 생성자를 통한 객체 초기화시 가독성이 현저히 떨어진다.
내가 정확한 위치에 정확한 값을 넣었는지 확인하고, 빠진 매개변수는 없는지 확인해야하는 번거로움이 생기게 된다.

Builder 패턴 사용

빌더 패턴은 생성자 패턴의 안정성과 자바빈즈 패턴의 가독성을 겸비한 패턴이다.

  1. 빌더는 생성할 클래스 안에 정적 멤버 클래스로 만들어두는것이 일반적이다.
  2. 빌더 클래스의 생성자는 Public으로 선언한다.
  3. 필수 변수, 선택 변수를 나누고 필수변수의 경우 Builder 생성자에서 초기화 시켜준다.
    빌더 패턴에도 단점이 존재한다.
    코드가 장황해지기 때문에 매개변수가 많을 경우 값어치를 하게 된다.
    이 부분은 Lombok의 @Builder를 사용해서 간략히 할 수 있다.
public class Member {
    private String name;
    private int age;
    
    //Member의 생성은 Builder를 통해서만 가능.
    private Member(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }
    
    public static Builder builder(){
        return new Builder();
    }
    
    protected static class Builder {
        private String name;
        private int age = 0;
       
        public Builder(String name) {	// Builder 생성시 필수값 초기화
        	this.name = name;
        }
        public Builder age(int age) {
            this.age = age;
            return this;
        }
        public Member build() {
            return new Member(this);
        }
    }
}
profile
3년차 Spring, Java 주니어 백엔드 개발자입니다.

0개의 댓글