JaeWon's Devlog
article thumbnail
반응형

개발을 하다 보면 생성자(Constructor)를 통해 객체 생성을 하게 된다. 해당 객체를 생성할 때 다양한 방법이 있겠지만, 보통 new 연산자를 통해 생성하곤 한다.

그러나 이러한 방법은 객체가 가지고 있는 변수(인자)들이 많아질 경우 해당 인자들이 어떠한 값인지 헷갈릴 경우가 있다. 또한 생성 시에도 필요치 않은 매개변수의 값까지 지정해야 하는 불편함도 있고, 코드를 한눈에 알아보기도 힘들다.

이러한 상황을 대비하여 빌드 패턴을 사용하여 생성자를 관리하면 조금 더 유연하게 관리할 수 있는데, 이를 정리해보고자 한다.


1. 빌더 패턴(Builder Pattern) 이란?

- 복잡한 객체를 생성하는 방법을 정의하는 클래스와 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴.

- 생성해야 되는 객체가 Optional 한 속성을 많이 가질 때 좋다.

1-1. 빌더 패턴은 생성 패턴(Creational Pattern) 중 하나

- 생성 패턴은 객체를 만드는 절차를 추상화하는 패턴.

- 객체를 생성하는 방법이나 객체의 표현 방법을 시스템과 분리.

  1. 시스템이 어떤 Concreate Class 를 사용하는지에 대한 정보를 캡슐화.
  2. 클래스의 인스턴스들이 어떻게 만들고, 어떻게 결합하는지에 대한 부분을 완전히 숨김.

2. 빌더 패턴을 사용해야 하는 이유

- 빌더 패턴을 사용 시에 장점은 아래와 같습니다.

  1. 필요한 데이터만 설정할 수 있다.
  2. 유연셩을 확보할 수 있다.
  3. 가독성을 높일 수 있다.
  4. 변경 가능성을 최소화할 수 있다.

- 위 장점들을 아래 Member 클래스를 통해서 예를 들어보도록 하겠습니다.

@NoArgsConstructor
@AllArgsConstructor
public class Member {
    private Long id;
    private String memberId;
    private String memberPw;
    private String memberName;
    private String memberPhone;
}

2-1. 필요한 데이터만 설정할 수 있다.

- 기본적으로 객체를 생성할 때, 필요 없는 변수가 있어도 해당 값을 더미 값으로 세팅하여 이외의 모든 변수를 받아 생성하거나, 필요한 변수만 작성된 생성자를 새로 만들어 생성하게 된다.

//	1. 모든 생성자(필요없는 변수(memberPw)는 더미)
Member member = new Member(1L, "test", null, "개발자", "01011113333");

//	2. 객체에 필요 변수만 있는 생성자
public class Member {
    private Long id;
    private String memberId;
    private String memberPw;
    private String memberName;
    private String memberPhone;
    
    public Member (String memberId, String memberName, String memberPhone) {
        this.memberId = memberId;
        this.memberName = memberName;
        this.memberPhone = memberPhone;
    }
}

 

- 해당 작업이 변경없이 유지가 된다면 좋겠지만, 요구사항은 변하기 마련이고, 변수가 많아질 경우에는 해당 작업으로 인해 개발 시간 낭비가 발생한다.

- 이러한 상황을 빌더를 통해 동적으로 처리할 수 있다.

//	ex1
Member member =Member.builder()
		.memberId("test")
                .memberName("개발자")
                .memberPhone("01011113333")
                .build();

//	ex2
Member member =Member.builder()
		.memberId("test")
                .memberName("개발자")
                .build();

2-2. 유연성을 확보할 수 있다.

- Member 클래스에 우편번호라는 변수를 추가해야 한다고 한다면, 다음 작업이 필요하다.

  • 전체 생성자를 다시 작성해야하고, 필요 변수만을 위한 생성자도 작성/수정이 필요하다.
  • 전체 생성자를 사용하고 있는 곳은 전부 수정이 필요하다.

- 1~2개 라면 괜찮지만, 50~100개일 경우 모든 로직을 수정해야 하는 불필요한 조치가 발생한다.

- 하지만, 빌더 패턴을 이용한다면 새로운 변수가 추가되더라도 기존의 코드에 영향을 주지 않을 수 있다.

2-3. 가독성을 높일 수 있다.

- 변수가 5 ~ 10개인 경우에는 생성자로 객체를 생성할 때, 위치에 따라 변수의 의미를 알 수 있다.(사실 자기가 개발한 것은 알겠지만, 남이 개발한 것은 알기 어렵다...)

- 위 Member 클래스의 생성자를 아래와 같이 생성해본다.

Member member = new Member(1L, "test", "test", "test", "test");

- 테스트하기 위해 모두 test로 작성하기도 하였지만, 실제로 비슷한 값이 들어올 경우 어떠한 변수에 해당하는 값인지 파악하기 어렵다.

- 하지만, 빌더 패턴을 사용하면 직관적으로 어떤 데이터를 어떤 변수에 세팅하는지 파악하기 쉽다.

Member member =Member.builder()
		.memberId("test")
        	.memberPw("test")
                .memberName("test")
                .memberPhone("test")
                .build();

2-4. 변경 가능성을 최소화할 수 있다.

- 개발시에 생성자에 대해 setter 를 많이 사용하게 된다. 하지만 이는 불필요한 변수의 변경 가능성을 열어 두는 것이다.

- 이러한 상황은 유지보수 시에 값이 할당된 지점을 찾아 파악해야 하는 불편한 점을 유발한다.

- 만약, 할당하는 시점이 객체의 생성 때 뿐이라면, 값이 잘못되었을 때 파악하기 쉬워지고 유지보수성이 높아질 것이다.

- 보통 변경 가능성을 최소화하는 방법으로는 변수에 final 을 선언하는 것이다.

@Builder
public class Member {
    private final Long id;
    private final String memberId;
    private final String memberPw;
    private final String memberName;
    private final String memberPhone;
}

- 하지만, final 을 붙일 수 없는 경우도 있는데, 이때에는 final 변수 없이 setter 자체를 구현하지 않음으로써 동일한 효과를 얻을 수 있다.

2-5. 빌더 패턴을 사용하지 않을 예외 케이스

- 객체를 생성 시에 보통은 빌더 패턴을 적용하는 것이 좋다.

- 물론 예외 케이스도 있을 수 있는데, 아래 2가지 상황에 대해서는 빌더 패턴을 구현할 필요가 없다.

  • 객체의 생성을 라이브러리로 위임하는 경우
  • 변수의 개수가 2개 이하이며, 변경 가능성이 없는 경우

- 변수의 개수와 변경 가능성 등을 중점적으로 보고 패턴을 적용할지 판단을 하면 된다.


참고

- https://mangkyu.tistory.com/163

- https://readystory.tistory.com/121

- https://velog.io/@injoon2019/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4

반응형

'디자인패턴' 카테고리의 다른 글

[디자인패턴] 전략(Strategy) 패턴  (0) 2023.04.21
[디자인패턴] 싱글톤(Singleton) 패턴  (0) 2022.01.16
profile

JaeWon's Devlog

@Wonol

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!