Builder Pattern이란?

생성자를 통해 객체를 생성하는데 있어 존재하는 단점을 피하고자 별도의 Builder 클래스를 사용해 객체를 생성하는 방식

 

* 생성자를 통한 객체 생성

Bag bag = new Bag("name", 1000, "memo");

 

*빌더 패턴을 사용한 객체 생성

Bag bag = Bag.builder()
		.name("name")
        	.money(1000)
        	.memo("memo")
        	.build();

 

왜 사용?

가독성 증대

Setter 없으므로 변경 불가능한 객체 생성 가능

한번에 객체를 반환하므로 객체 일관성 유지 가능

필수 인자 지정 가능

Null 이 들어가는 값에 대해 명시적으로 표현하지 않아도 됨

 

 

* 기존 생성자를 활용할 경우

Person person = new Person("John", 25, null, null, null);

 

각 인자가 무슨 데이터를 의미하는지 알기 쉽지 않을 뿐더러 3~5번째 인자는 값이 필요 없음에도 null이라는 값을 넣어서 생성해야 함

 

 

* 빌더 패턴을 활용할 경우

Person person = Person.builder()
		.name("John")
            .age(25)
            .build();

데이터가 필요없는 값은 따로 null을 주지 않아도 됨

John은 name, 25는 age라는 데이터를 의미한다는 것을 쉽게 확인 가능

 

 

 

빌더 패턴 구현

public class Person {
    private String name;
    private int age;
    private String gender;
    private String job;


    public String getName(){
        return name;
    }

    public int getAge(){
        return age;
    }

    public String getGender(){
        return gender;
    }

    public String getJob(){
        return job;
    }

    Person(Builder builder){
    }

    public static class Builder{

        private String name;
        private int age;
        private String gender;
        private String job;

        public Builder(String name){
            this.name = name;
        }

        public Builder age(int age){
            this.age = age;
            return this;
        }
        
        public Builder gender(String gender){
            this.gender = gender;
            return this;
        }
        
        public Builder job(String job){
            this.job = job;
            return this;
        }
        
        public Person build(){
            return new Person(this);
        }
    }
}

Person 클래스에 빌더패턴을 위한 Builder 클래스 구현

 

 Person person = new Builder("John")
            .age(25)
            .gender("male")
            .job("programmer")
            .build();

위와 같이 빌더패턴으로 객체 생성 가능

 

 

 

@Builder

lombok에서 제공하는 어노테이션

위와 같은 Builder클래스를 직접 구현하지 않고도 Builder pattern 사용 가능

 

@Builder
public class Person {
    private String name;
    private int age;
    private String gender;
    private String job;
 }

@Builder 어노테이션을 붙이기만 하면

 

Person person = Person.builder()
		.name("John")
            .age(25)
            .gender("male")
            .job("programmer")
            .build()

 위와 같이 빌더패턴 사용 가능

 

 

@Builder 옵션

 

builderMethodName

@Builder 어노테이션의 빌더 생성하는 메소드의 기본 이름은 builder

이 이름을 변경할 수 있는 옵션

@Builder(builderMethodName = "builder")

 

 

buildMethodName

builder 메소드로 얻은 빌더에 필드 값을 삽입하고 마지막에 객체를 생성하는 메소드인 build 메소드의 이름을 변경할 수 있는 옵션

@Builder(builderMethodName = "builder", buildMethodName = "build")

 

builderClassName

내부의 Builder 클래스의 이름을 변경하는 옵션

@Builder(builderMethodName = "builder", buildMethodName = "build", builderClassName = "builderClass")

 

 

 

내부 Builder 클래스 이름의 경우 바꿀 필요가 없을 것 같은데 왜 사용?

 

public class User {
 
    private String userId;
 
    private String password;
 
    private String email;
 
    private Long point;
 
    private String hobby;
 
    @Builder(builderMethodName = "userBuilder")
    private User(String userId, String password, String email) {
        this.userId = userId;
        this.password = password;
        this.email = email;
    }
 
    @Builder(builderMethodName = "anonymousBuilder")
    private User(String userId, String password) {
        this.userId = userId;
        this.password = password;
    }
 
    @Builder(builderMethodName = "allBuilder")
    private User(String userId, String password, String email, Long point, String hobby) {
        this.userId = userId;
        this.password = password;
        this.email = email;
        this.point = point;
        this.hobby = hobby;
    }
 
    @Builder(builderMethodName = "updateBuilder")
    private User(Long point) {
        this.point = point;
    }
 
}

위와 같이 2개 이상의 생성자에 @Builder 를 사용하는 경우

내부 Builder 클래스의 이름이 같기 때문에 하나의 @Builder만 적용

이를 해결하기 위해 builderClassName, builderMethodName 함께 사용

 

 

builderMethodName 

boolean 값으로 설정할 수 있는 어노테이션

이 값을 true로 설정 시 builder로 만든 인스턴스에서 toBuilder() 메소드를 호출하여 그 인스턴스의 값을 베이스로 빌더 패턴을 만들어 새로운 인스턴스 생성 가능

 

@Builder(toBuilder = true)
public class Person {
    private String name;
    private int age;
    private String gender;
    private String job;
}

 

 

위와 같은 클래스에서 toBuilder = true 로 설정하게 되면

 

 

Person firstPerson = Person.builder().name("john").age(25).job("programmer").build();
Person secPerson = firstPerson.toBuilder().name("Dave").build();

이름이 John, 나이가 25, 직업이 programmer인 firstPerson 객체를 생성한 후

나이, 직업은 위와 동일하지만 이름은 Dave로 다른 새로운 객체인 secPerson을 손쉽게 생성 가능

 

access

Builder의 접근 제한자를 설정하는 옵션

@Builder(access = AccessLevel.PRIVATE)

 

'끄적 > lombok' 카테고리의 다른 글

lombok  (0) 2022.12.29
@Getter @Setter  (0) 2022.12.29
@AllArgsConstructor @NoArgsConstructor @RequiredArgsConstructor  (0) 2022.12.28

+ Recent posts