본문 바로가기

java

빌더 패턴은 얼마나 유용한가?

 - 필드가 많은 객체를 생성할 경우 생성자를 이용하면 다루기도 어렵고 헷갈릿 수 있다,

private final Animal animal;
private final String petName;
private final String ownerName;
private final String address;
private final String telephone;
private final Date dateOfBirth;
private final String emailAddress;

 - 유효한 Pet 객체를 만들려면 필요한 모든 필드와 조합할 수 있는 옵션 필드를 포함하도록 많은 매개변수를 갖는 생성자가 최소한 4개는 필요하다.

 - 이러한 문제를 해결하는 한 가지 방법은 생성자를 사용하지 않는 것.

 - 필드에서 final을 제거하고 Pet 객체에 setter 객체를 사용


finla Pet p = new Pet();

p.setEmailAddress("owners@address.com");


- 유효하지 않는  Pet 객체를 생성할 수 있다는 점에 주의 해야 하고 Pet 객체를 정의 할 때는 animal, perName, ownerName, address, telephone 필드가 모두 채워져 있어야 한다,


 - 이런 상황일 때 빌더 패턴을 사용하면 도움이 된다.


public class PetTest {
@Test
public void legalBuild() {
final Pet.Builder builder = new Pet.Builder();
final Pet pet = builder.withAnimal(Pet.Animal.CAT).withPetName("Squidge").withOwnerName("Simon Smith").withAddress("123 High Street")
.withTelephone("0770777070").withEmailAddress("simon@email.com").build();
}

@Test(expected = IllegalStateException.class)
public void illegalBuild() {
final Pet.Builder builder = new Pet.Builder();
final Pet pet = builder.withAnimal(Pet.Animal.CAT).withPetName("Squidge").withOwnerName("Simon Smith").build();
}
}

 - Builder 클래스는 Pet 클래스의 일부이며 Pet 객체를 생성하는 전적인 권한이 있다.

 - 생성자는 final 키워드를 뺀 private으로 선언할 수 있다.


public class Pet {
public enum Animal {
CAT, DOG, ETC
}
public static class Builder {
private Animal animal;
private String petName;
private String ownerName;
private String address;
private String telephone;
private Date dateOfBirth;
private String emailAddress;

public Builder withAnimal(final Animal animal) {
this.animal = animal;
return this;
}
public Builder withPetName(final String petName) {
this.petName = petName;
return this;
}
public Builder withOwnerName(final String ownerName) {
this.ownerName = ownerName;
return this;
}
public Builder withAddress(final String address) {
this.address = address;
return this;
}
public Builder withTelephone(final String telephone) {
this.telephone = telephone;
return this;
}
public Builder withDateOfBirth(final Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
return this;
}
public Builder withEmailAddress(final String emailAddress) {
this.emailAddress = emailAddress;
return this;
}

public Pet build() {
if (animal == null || petName == null || ownerName == null || address == null || address == null || telephone == null) {
throw new IllegalStateException("Connot create Pet");
}

return new Pet(animal, petName, ownerName, address, telephone, dateOfBirth, emailAddress);
}
}

private final Animal animal;
private final String petName;
private final String ownerName;
private final String address;
private final String telephone;
private final Date dateOfBirth;
private final String emailAddress;

private Pet(final Animal animal, final String petName, final String ownerName, final String address, final String telephone, final Date dateOfBirth, final String emailAddress) {
this.animal = animal;
this.petName = petName;
this.ownerName = ownerName;
this.address = address;
this.telephone = telephone;
this.dateOfBirth = dateOfBirth;
this.emailAddress = emailAddress;
}


public class LibraryBookTest {
@Test
public void fictionLibraryBook() {
final LibraryBook.Builder builder = new LibraryBook.Builder();
final LibraryBook book = builder.withBookName("War and Peace").build();

assertEquals(LibraryBook.BookType.FICTION, book.getBookType());
}
}
public class LibraryBook {
public enum BookType {
FICTION, FILE, PET
}
public static class Builder {
private BookType bookType = BookType.FICTION;
private String bookName;

public Builder withBookType(final BookType bookType) {
this.bookType = bookType;
return this;
}
public Builder withBookName(final String bookName) {
this.bookName = bookName;
return this;
}

public LibraryBook build() {
return new LibraryBook(bookType, bookName);
}
}

private final BookType bookType;
private final String bookName;

public LibraryBook(final BookType bookType, final String bookName) {
this.bookType = bookType;
this.bookName = bookName;
}

public BookType getBookType() {
return bookType;
}
}