빌더 패턴(Builder) + @Build 어노테이션

sarah·2023년 2월 2일
0

디자인 패턴

목록 보기
1/1

빌더 패턴이란?

The builder pattern is used in software development to construct complex objects in a step-by-step manner, without having to specify the complex details of object creation in the main code.

⇒ 복잡한 객체들을 단계별로 생성할 수 있도록 하는 생성 디자인 패턴

// 다양한 생성자를 통한 객체 생성
public class User {
	private final String firstName;    // 필수값
	private final String lastName;     // 필수값
	private int age;                   // 선택값
	private String phone;              // 선택값

	public User(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	public User(String firstName, String lastName, int age) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
	}

	public User(String firstName, String lastName, String phone) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.phone = phone;
	}
User user1 = new User("John", "Doe");
User user2 = new User("John", "Doe", 30);
User user3 = new User("John", "Doe", "123456789");

빌더 패턴을 사용하여 객체를 생성할 경우 장점

  1. 불필요한 생성자를 제거할 수 있다.
  2. 생성자의 인자 순서에 상관없이 객체 생성이 가능하다.
  3. setter 메서드가 없으므로 변경 불가능한 객체를 만들 수 있다.
  4. 객체 생성 시 어떤 데이터를 셋팅하는지 파악 가능하여 가독성을 높여준다.
public class User {
	private final String firstName;
	private final String lastName;
	private final int age;
	private final String phone;
	
	private User(UserBuilder builder) {
		this.firstName = builder.firstName;
		this.lastName = builder.lastName;
		this.age = builder.age;
		this.phone = builder.phone;
	}

	public static class UserBuilder {
		private final String firstName;    // 필수값
		private final String lastName;     // 필수값
		private int age;                   // 선택값
		private String phone;              // 선택값

		public UserBuilder(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		public UserBuilder age(int age) {
			this.age = age;
			return this;
		}

		public UserBuilder phone(String phone) {
			this.phone = phone;
			return this;
		}

		public User build() {
			return User(this.firstName, this.lastName, this.age, this.phone);
		}
    }
 }
User user = new User.UserBuilder("John", "Doe")
	.age(30)
	.phone("123445678")
	.build();

Lombok @Builder 어노테이션 사용

@Builder 어노테이션은 Builder Pattern을 사용하여 객체를 생성하도록 도와준다.
클래스 레벨과 생성자 레벨에 선언하여 사용할 수 있다.

클래스 레벨

⇒ 클래스 레벨에 @Builder 어노테이션을 선언하면, @AllArgsConstructor(access=AccessLevel.PACKAGE) 와 동일하게 생성자를 생성한다.

⇒ 주의: 다른 생성자가 이미 있을 경우 제대로 동작하지 않을 수 있다.

@Builder
public class User {
	private String firstName;
	private String lastname;
	private int age;
	private String phone;
}
// 컴파일 후
public class User {
	private String firstName;
	private String lastName;
	private int age;
	private String phone;
	
	User(final String firstName, final String lastName, final int age, final String phone) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
		this.phone = phone;
	}

	public static UserBuilder builder() {
		return new UserBuilder();
	}

	public static class UserBuilder {
		private String firstName;
		private String lastName;
		private int age;
		private String phone;

		public UserBuilder() {}

		public UserBuilder firstName(final String firstName) {
			this.firstName = firstName;
			return this;
		}

		public UserBuilder lastName(final String lastName) {
			this.lastName = lastName;
			return this;
		}

		public UserBuilder age(final int age) {
			this.age = age;
			return this;
		}

		public UserBuilder phone(final String phone) {
			this.phone = phone;
			return this;
		}
		
		public User build() {
			return User(this.firstName, this.lastName, this.age, this.phone);
		}

		public String toString() {
			return "User.UserBuilder(firstName=" + this.firstName + ", lastName=" + this.lastName + ", age=" + this.age + ", phone=" + this.phone + ")";
    	}
	}
}
User user = new User.builder()
	.firstName("John")
	.lastName("Doe")
	.age(30)
	.phone("123456789")
	.build();

생성자 레벨

⇒ 클래스 레벨과 다른점은 생성자에 선언한 파라미터 필드에 한해서반 빌드 패턴이 적용된다는 것이다.

public class User {
	private String firstName;
	private String lastName;
	private int age;
	private String phone;

	@Builder
	User(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
}
// 컴파일 후
public class User {
	private String firstName;
	private String lastName;
	private int age;
	private String phone;

	User(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public static UserBuilder builder() {
		return new UserBuilder();
	}

	public static class UserBuilder {
		private String firstName;
		private String lastName;

		public UserBuilder() {}

		public UserBuilder firstName(final String firstName) {
			this.firstName = firstName;
			return this;
		}

		public UserBuilder lastName(final String lastName) {
			this.lastName = lastName;
			return this;
		}

		public User build() {
			return new User(this.firstName, this.lastName);
		}

		public String toString() {
			return "User.UserBuilder(firstName=" + this.firstName + ", lastName=" + this.lastName + ")";
    	}
	}
}
User user = new User.builder()
	.firstName("John")
    .lastName("Doe")
    .build();

0개의 댓글