본문 바로가기
공부/프로그래밍

[java] builder 패턴, 객체를 안전하게 생성하기

by demonic_ 2020. 1. 29.
반응형

객체를 생성할 때 파라미터가 많으면 빌더패턴을 사용 시 생성이 편리하다. 우선

1. 순서에 상관없이 객체생성이 가능하고

2. 인자가 많아도 안전하게 생성

등 장점이 있다.

그런데 빌더패턴을 쓰다보면 한가지 걸리는 것이 있다. 바로 필수값 체크(Not null)다.

Book 이라는 객체가 있다고 해보자. 진행의 편의성을 위해 Lombok 을 이용했다.

import lombok.Builder;
import lombok.ToString;

@ToString
public class Book {

    private String bookName;
    private String author;
    private Integer price;


    @Builder
    public Book(String bookName, String author, Integer price) {
        this.bookName = bookName;
        this.author = author;
        this.price = price;
    }
}

 

Book 객체를 생성한다

public class TestMainClass {


    public static void main(String[] args) {
        Book book = Book.builder()
                .bookName("나는 바람처럼 자유롭다")
                .author("최인호")
                .price(1000)
                .build();

        System.out.println("book = " + book);


        Book book2 = Book.builder()
                .price(1000)
                .build();

        System.out.println("book2 = " + book2);
    }
}

 

 수행하면 다음과 같은 로그가 보인다

book = Book(bookName=나는 바람처럼 자유롭다, author=최인호, price=1000)
book2 = Book(bookName=null, author=null, price=1000)

 

 

그런데 bookName 이 not null 이라면 위와같은 생성방식은 추후 문제를 일으키게 된다.

때문에 Assert 를 이용해 생성시 사전에 방지하는 것이 좋다.

import lombok.Builder;
import lombok.ToString;
import org.springframework.util.Assert;

@ToString
public class Book {

    private String bookName;
    private String author;
    private Integer price;


    @Builder
    public Book(String bookName, String author, Integer price) {
        Assert.hasText(bookName, "책이름이 없습니다");
        Assert.hasText(author, "저자명이 없습니다");

        this.bookName = bookName;
        this.author = author;
        this.price = price;
    }
}

 

이제 다시 실행해보면 IllegalArgumentException 가 발생한다

book = Book(bookName=나는 바람처럼 자유롭다, author=최인호, price=1000)
Exception in thread "main" java.lang.IllegalArgumentException: 책이름이 없습니다
	at org.springframework.util.Assert.hasText(Assert.java:284)
	at kr.sample.ob.Book.<init>(Book.java:18)
	at kr.sample.ob.Book$BookBuilder.build(Book.java:16)
	at kr.sample.TestMainClass.main(TestMainClass.java:20)

 

조금 불편하더라도 추후 에러가 발생할 걸 생각하면 반드시 입력해주는 것이 좋다.

 

 

혹은 간단하게 사용하는 것이라면 lombok에서 제공하는 @NonNull 을 추천한다.

사용방법은 파라미터에 어노테이션을 달아주는 것이고 다음과 같다.

    @Builder
    public Book(@NonNull String bookName, @NonNull String author, Integer price) {
        this.bookName = bookName;
        this.author = author;
        this.price = price;
    }

 

 

에러메세지

book = Book(bookName=나는 바람처럼 자유롭다, author=최인호, price=1000)
Exception in thread "main" java.lang.NullPointerException: bookName is marked non-null but is null
	at kr.sample.ob.Book.<init>(Book.java:15)
	at kr.sample.ob.Book$BookBuilder.build(Book.java:14)
	at kr.sample.TestMainClass.main(TestMainClass.java:16)

메세지를 커스텀 할 수 없다는 단점이 있지만 이정도면 쓸만할 듯 하다.

 

 

끝.

 

반응형

댓글