본문 바로가기
Java/Spring

Spring) Builder Pattern - 흐름 파악, @Builder

by 박채니 2022. 9. 10.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.

 

Builder Pattern

- GoF의 디자인 패턴(생성패턴)

- 필드가 여러 개일 경우, 필드 값을 개별적으로 등록 후 객체를 생성하는 방법

 

Builder 흐름 파악하기

 

User

public class User {
	private long code; // pk
	private String username; // 유저아이디
	private String password;
	private String name;
	private LocalDate birthday;
	private String phone;
	private boolean married;
	
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	public User(long code, String username, String password, String name, LocalDate birthday, String phone,
			boolean married) {
		super();
		this.code = code;
		this.username = username;
		this.password = password;
		this.name = name;
		this.birthday = birthday;
		this.phone = phone;
		this.married = married;
	}
	
	public static class Builder {
		private long code; // pk
		private String username; // 유저아이디
		private String password;
		private String name;
		private LocalDate birthday;
		private String phone;
		private boolean married;
		
		public Builder code(long code) {
			this.code = code;
			return this; // Builder객체 자신을 반환
		}
		public Builder username(String username) {
			this.username = username;
			return this; 
		}
		public Builder password(String password) {
			this.password = password;
			return this; 
		}
		public Builder name(String name) {
			this.name = name;
			return this; 
		}
		public Builder birthday(LocalDate birthday) {
			this.birthday = birthday;
			return this; 
		}
		public Builder phone(String phone) {
			this.phone = phone;
			return this; 
		}
		public Builder married(boolean married) {
			this.married = married;
			return this; 
		}
		
		public User build() {
			return new User(code, username, password, name, birthday, phone, married);
		}
	}
	
	public static Builder builder() {
		return new Builder();
	}

	@Override
	public String toString() {
		return "User [code=" + code + ", username=" + username + ", password=" + password + ", name=" + name
				+ ", birthday=" + birthday + ", phone=" + phone + ", married=" + married + "]";
	}
}

User 클래스의 내부 클래스로 Builder 클래스가 존재하며, User 클래스가 가지고 있는 필드를 그대로 가지고 있습니다.

 

 

UserMain

public class UserMain {

	public static void main(String[] args) {
		User u1 = User.builder() // User.Builder객체
					.code(1L)
					.username("honggd")
					.password("1234")
					.name("홍길동")
					.birthday(LocalDate.of(1999, 9, 9))
					.phone("01012341234")
					.married(false)
					.build(); // User객체
		System.out.println(u1);
		
		User u2 = User.builder()
				.username("honggd")
				.password("1234")
				.build();
		System.out.println(u2);
	}

}

@콘솔출력값
User [code=1, username=honggd, password=1234, name=홍길동, birthday=1999-09-09, phone=01012341234, married=false]
User [code=0, username=honggd, password=1234, name=null, birthday=null, phone=null, married=false]

User.builder() 를 호출하면 builder() 메소드에 의하여 User의 내부클래스인 Builder 객체가 리턴됩니다.

Builder객체에 원하는 필드를 set해주며, 해당 메소드들은 모두 return this → 자기자신을 리턴해줍니다.

build() 메소드를 이용해 User의 파라미터 생성자를 생성 후 User 객체를 리턴해줍니다.

 

따라서 원하는 값만 값을 setting할 수 있는 것이죠.

 

이클립스에서는 builder를 생성하는 단축키가 별도 없으므로 Lombok을 이용해줍니다.


@Builder 사용

 

Client

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Client {
	private long code; // pk
	private String username; // 유저아이디
	private String password;
	private String name;
	private LocalDate birthday;
	private String phone;
	private boolean married;
}

@Builder에 의해서 전체 파라미터 생성자가 생성되지만, 기본 생성자가 만들어지지 않아 @NoArgsConstructor를 사용해주면 오류가 발생합니다.

만들어준 전체 파라미터 생성자가 기본 생성자로 오버라이딩 되기 때문입니다.

명시적으로 만들어주면 해결!!

 

 

ClientMain

    Client c1 = Client.builder()
            .code(1L)
            .username("honggd")
            .password("1234")
            .name("홍길동")
            .birthday(LocalDate.of(1999, 9, 9))
            .phone("01012341234")
            .married(false)
            .build();
    System.out.println(c1);

    Client c2 = Client.builder()
            .username("honggd")
            .password("1234")
            .build();
    System.out.println(c2);
    
@콘솔출력값
Client(code=1, username=honggd, password=1234, name=홍길동, birthday=1999-09-09, phone=01012341234, married=false)
Client(code=0, username=honggd, password=1234, name=null, birthday=null, phone=null, married=false)