Joshua Bloch's Builder Pattern - kuyeol/Document GitHub Wiki
ν¨κ³Όμ μΈ Java κ°μ²΄ μμ±μ μν Builder ν¨ν΄ κ°μ΄λ
Builder ν¨ν΄μ κ°λ , μ₯μ , μ€μ μ½λ μμ
[!Tip] λ§μ λ§€κ°λ³μλ₯Ό κ°μ§ κ°μ²΄λ₯Ό μ΄λ»κ² μμ νκ³ κ°λ μ± λκ² μμ±ν μ μμκΉ?
Joshua Blochκ° γEffective Javaγμμ μ μν Builder ν¨ν΄μ
"ν λ μ€μ½ν μμ±μ"μ λ¨μ μ 극볡νκ³ ,
볡μ‘ν κ°μ²΄ μμ±μ λ μ½κΈ° μ½κ³ μ μ°νλ©° μμ νκ² λ§λ€μ΄μ€λλ€.
1. λ¬Έμ μ : ν λ μ€μ½ν μμ±μμ κ·Έ νκ³
μλ°μμ μ¬λ¬ λ§€κ°λ³μκ° νμν κ°μ²΄λ₯Ό μμ±ν λ,
"ν
λ μ€μ½ν μμ±μ(Telescoping Constructor) ν¨ν΄" μ νν μ¬μ©ν©λλ€.
νμ§λ§, μ΄ λ°©μμ λ€μκ³Ό κ°μ λ¬Έμ λ₯Ό μκ³ μμ΅λλ€.
[!caution] ν λ μ€μ½ν μμ±μ ν¨ν΄
μ νμ λ§€κ°λ³μκ° λμ΄λ μλ‘ μμ±μ μ€λ²λ‘λ©μ΄ νμ¦νκ³ ,
μ½λκ° λΆνμνκ² λ³΅μ‘ν΄μ§λλ€.
νΉν, λ§€κ°λ³μκ° λ§κ³ νμ μ΄ κ°μΌλ©΄ μ€μν μνμ΄ λμμ§λλ€.
μμ: Book ν΄λμ€μ ν λ μ€μ½ν μμ±μ
// μν° ν¨ν΄: ν
λ μ€μ½ν μμ±μ
public class Book {
private final String isbn; // νμ
private final String title; // νμ
private final String author; // μ ν
private final int publicationYear; // μ ν
private final String description; // μ ν
public Book(String isbn, String title) {
this(isbn, title, null);
}
public Book(String isbn, String title, String author) {
this(isbn, title, author, 0);
}
public Book(String isbn, String title, String author, int publicationYear) {
this(isbn, title, author, publicationYear, "N/A");
}
public Book(String isbn, String title, String author, int publicationYear, String description) {
this.isbn = isbn;
this.title = title;
this.author = author;
this.publicationYear = publicationYear;
this.description = description;
}
@Override
public String toString() {
return "Book{" +
"isbn='" + isbn + '\'' +
", title='" + title + '\'' +
", author='" + author + '\'' +
", publicationYear=" + publicationYear +
", description='" + description + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) {
// νμ λ§€κ°λ³μλ§
Book book1 = new Book("978-0321765723", "Effective Java");
// λͺ¨λ λ§€κ°λ³μ
Book book2 = new Book("978-1617294945", "Spring in Action", "Craig Walls", 2018, "A comprehensive guide to Spring Framework.");
// μΌλΆ μ ν λ§€κ°λ³μ
Book book3 = new Book("978-0134685991", "Clean Code", "Robert C. Martin", 2008);
System.out.println(book1);
System.out.println(book2);
System.out.println(book3);
}
}
μΆλ ₯:
Book{isbn='978-0321765723', title='Effective Java', author='null', publicationYear=0, description='N/A'}
Book{isbn='978-1617294945', title='Spring in Action', author='Craig Walls', publicationYear=2018, description='A comprehensive guide to Spring Framework.'}
Book{isbn='978-0134685991', title='Clean Code', author='Robert C. Martin', publicationYear=2008, description='N/A'}
λ¨μ μμ½
[!warning]
- κ°λ μ± μ ν: λ§€κ°λ³μ μμμ μλ―Έλ₯Ό νμ νκΈ° μ΄λ ΅κ³ , μ€μνκΈ° μ½λ€.
- μ μ§λ³΄μ μ΄λ €μ: μλ‘μ΄ μ ν λ§€κ°λ³μ μΆκ° μ μμ±μ μΆκ°Β·μμ νμ.
- nullμ λͺ¨νΈν¨: μ ν νλμ null μ λ¬ μ μ½λμ μλκ° λΆλΆλͺ .
- μμ±μ νμ¦: μ‘°ν©λ§νΌ μμ±μκ° λμ΄λ ν΄λμ€κ° λΉλν΄μ§.
2. ν΄κ²°μ± : Joshua Blochμ Builder ν¨ν΄
[!note] Builder ν¨ν΄μ
κ°μ²΄ μμ± κ³Όμ μ μ¬λ¬ λ¨κ³λ‘ λͺ νν λλμ΄
κ°λ μ±κ³Ό μμ μ±μ λͺ¨λ μ‘μ μ μκ² ν΄μ€λλ€.
ν΅μ¬ μμ΄λμ΄
[!tip]
- κ°μ²΄ λ΄λΆμ
static nested class
λ‘ Builder μ μ- μλ κ°μ²΄μ μμ±μλ
private
- νμ νλλ Builder μμ±μμμ, μ ν νλλ λ©μλ 체μ΄λμΌλ‘
- λ§μ§λ§μ
build()
λ‘ κ°μ²΄ μμ±
μμ : Book ν΄λμ€μ Builder ν¨ν΄ μ μ©
import java.time.Year;
public class Book {
private final String isbn; // νμ
private final String title; // νμ
private final String author; // μ ν
private final Year publicationYear; // μ ν
private final String description; // μ ν
// 1. private μμ±μ (Builderλ‘λ§ μμ±)
private Book(Builder builder) {
this.isbn = builder.isbn;
this.title = builder.title;
this.author = builder.author;
this.publicationYear = builder.publicationYear;
this.description = builder.description;
}
@Override
public String toString() {
return "Book{" +
"isbn='" + isbn + '\'' +
", title='" + title + '\'' +
", author='" + author + '\'' +
", publicationYear=" + publicationYear +
", description='" + description + '\'' +
'}';
}
public static class Builder {
private final String isbn;
private final String title;
private String author = null;
private Year publicationYear = null;
private String description = "No description available.";
public Builder(String isbn, String title) {
if (isbn == null || title == null) {
throw new IllegalArgumentException("ISBN and Title cannot be null.");
}
this.isbn = isbn;
this.title = title;
}
public Builder author(String author) {
this.author = author;
return this;
}
public Builder publicationYear(Year publicationYear) {
this.publicationYear = publicationYear;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Book build() {
return new Book(this);
}
}
}
public class Main {
public static void main(String[] args) {
// νμ λ§€κ°λ³μλ§
Book book1 = new Book.Builder("978-0321765723", "Effective Java").build();
// λͺ¨λ λ§€κ°λ³μ
Book book2 = new Book.Builder("978-1617294945", "Spring in Action")
.author("Craig Walls")
.publicationYear(Year.of(2018))
.description("A comprehensive guide to Spring Framework.")
.build();
// μΌλΆ μ ν λ§€κ°λ³μ (μμ 무κ΄)
Book book3 = new Book.Builder("978-0134685991", "Clean Code")
.publicationYear(Year.of(2008))
.author("Robert C. Martin")
.build();
System.out.println(book1);
System.out.println(book2);
System.out.println(book3);
}
}
μΆλ ₯:
Book{isbn='978-0321765723', title='Effective Java', author='null', publicationYear=null, description='No description available.'}
Book{isbn='978-1617294945', title='Spring in Action', author='Craig Walls', publicationYear=2018, description='A comprehensive guide to Spring Framework.'}
Book{isbn='978-0134685991', title='Clean Code', author='Robert C. Martin', publicationYear=2008, description='No description available.'}
3. Builder ν¨ν΄ μ¬μ© λ°©λ²
μ μ½λμ κ°μ΄ Builder ν¨ν΄μ μ¬μ©νλ©΄,
νμ λ§€κ°λ³μλ§ μ¬μ©ν μλ μκ³ ,
νμμ λ°λΌ μΌλΆ λλ λͺ¨λ μ ν λ§€κ°λ³μλ₯Ό μμ λ‘κ² μΆκ°ν μ μμ΅λλ€.
[!note] μ€ν κ²°κ³Ό
- νμ κ°λ§ μ§μ μ: author, publicationYear, descriptionμ κΈ°λ³Έκ°
- μΌλΆ κ°λ§ μ§μ μ: μνλ κ°λ§ 체μ΄λ
- λͺ¨λ κ° μ§μ μ: λͺ¨λ νλ κ° μ λ ₯ κ°λ₯
4. Builder ν¨ν΄μ μ₯μ μμ½
[!important] μ₯μ μ 리
- κ°λ μ±: μ΄λ€ νλμ μ΄λ€ κ°μ΄ λ€μ΄κ°λμ§ λͺ ν
- μ μ°μ±: νμν νλλ§ μ νμ μΌλ‘, μμμ μκ΄μμ΄ μ§μ κ°λ₯
- λΆλ³ κ°μ²΄ μμ±: build() μ κΉμ§λ λ―Έμμ±, μμ± νμ λΆλ³(final)
- μ ν¨μ± κ²μ¬: build()μμ λͺ¨λ νλμ μ ν¨μ± μΌκ΄ κ²μ¬ κ°λ₯
- μμ±μ λ립 λ°©μ§: μμ±μ νμ¦ μμ
5. μΈμ Builder ν¨ν΄μ μ νν κΉ?
[!important] Builder ν¨ν΄ μ μ© μΆμ² μν©
- μμ±μ/μ μ ν©ν 리 λ©μλ νλΌλ―Έν°κ° 4κ° μ΄μμΌ λ
- μ νμ λ§€κ°λ³μκ° λ§μ λ
- κ°μ²΄κ° **λΆλ³(immutable)**μ΄μ΄μΌ ν λ
- κ°μ²΄ μμ± κ³Όμ μ΄ λ³΅μ‘νκ±°λ λ¨κ³μ μΌ λ
6. Record && Builder ν¨ν΄ μ‘°ν©
Javaμ λ μ½λλ λΆλ³ λ°μ΄ν° κ°μ²΄ μμ±μ κ°λ¨νκ² ν΄μ£Όμ§λ§,
μ νμ νλκ° λ§κ³ μ μ°ν μμ±μ΄ νμνλ€λ©΄ μ¬μ ν λΉλ ν¨ν΄μ΄ μ μ©ν©λλ€.
[!note] λ μ½λμ λΉλ λμ μ¬μ©
- λ μ½λλ λͺ¨λ νλλ₯Ό ν λ²μ μΈν , μμ±μ/ν©ν 리μμ λΉλ νμ© κ°λ₯
- μ νμ νλκ° λ§κ±°λ, λΉλ μ€νμΌ APIλ₯Ό μν λ μ μ©
import java.time.Year;
public record BookRecord(String isbn, String title, String author, Year publicationYear, String description) {
public static class Builder {
private final String isbn;
private final String title;
private String author;
private Year publicationYear;
private String description;
public Builder(String isbn, String title) {
this.isbn = isbn;
this.title = title;
}
public Builder author(String author) { this.author = author; return this; }
public Builder publicationYear(Year year) { this.publicationYear = year; return this; }
public Builder description(String desc) { this.description = desc; return this; }
public BookRecord build() {
return new BookRecord(isbn, title, author, publicationYear, description);
}
}
public static Builder builder(String isbn, String title) {
return new Builder(isbn, title);
}
}
public class Main {
public static void main(String[] args) {
// νμ λ§€κ°λ³μλ§
BookRecord record1 = BookRecord.builder("978-0321765723", "Effective Java").build();
// λͺ¨λ λ§€κ°λ³μ
BookRecord record2 = BookRecord.builder("978-1617294945", "Spring in Action")
.author("Craig Walls")
.publicationYear(Year.of(2018))
.description("A comprehensive guide to Spring Framework.")
.build();
// μΌλΆ μ ν λ§€κ°λ³μ
BookRecord record3 = BookRecord.builder("978-0134685991", "Clean Code")
.author("Robert C. Martin")
.publicationYear(Year.of(2008))
.build();
System.out.println(record1);
System.out.println(record2);
System.out.println(record3);
}
}
μΆλ ₯:
BookRecord[isbn=978-0321765723, title=Effective Java, author=null, publicationYear=null, description=null]
BookRecord[isbn=978-1617294945, title=Spring in Action, author=Craig Walls, publicationYear=2018, description=A comprehensive guide to Spring Framework.]
BookRecord[isbn=978-0134685991, title=Clean Code, author=Robert C. Martin, publicationYear=2008, description=null]
κ²°λ‘
[!important]
- 볡μ‘ν κ°μ²΄λ₯Ό μ°μνκ² μμ±νκ³
- μ½λμ κ°λ μ±μ λμ΄λ©°
- λΆλ³ κ°μ²΄λ₯Ό μ½κ² λ§λ€ μ μμ
λ§€κ°λ³μκ° λ§κ³ , μΌλΆκ° μ΅μ μ΄λΌλ©΄ λΉλ ν¨ν΄μ μ κ·Ήμ μΌλ‘ μ μ©!
μ°Έκ³ :