|
| 1 | +--- |
| 2 | +title: Builder |
| 3 | +category: Creational |
| 4 | +language: ko |
| 5 | +tags: |
| 6 | +- Gang of Four |
| 7 | +--- |
| 8 | + |
| 9 | +## 의도 |
| 10 | + |
| 11 | +동일한 구성 프로세스가 다른 표현을 생성할 수 있도록 복잡한 객체의 구성을 해당 표현과 분리합니다. |
| 12 | + |
| 13 | +## 설명 |
| 14 | + |
| 15 | +실제 예제 |
| 16 | + |
| 17 | +> 롤플레잉 게임의 캐릭터 생성기를 상상해 보세요. 가장 쉬운 옵션은 컴퓨터가 사용자를 위해 문자를 만들도록 하는 것입니다. 직업, 성별, 머리색 등 캐릭터 세부 정보를 수동으로 선택하려면 캐릭터 생성은 모든 선택이 준비되었을 때 완료되는 단계별 프로세스가 됩니다. |
| 18 | +
|
| 19 | +쉽게 말하자면 |
| 20 | + |
| 21 | +> 생성자의 오염을 방지하면서 객체의 다른 맛들을 만들 수 있습니다. 여러 가지 맛의 객체가 있을 때 유용합니다. 또는 개체를 만드는 데 많은 단계가 수반될 때 유용합니다. |
| 22 | +
|
| 23 | +Wikipedia에 의하면 |
| 24 | + |
| 25 | +> 빌더 패턴은 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)에 대한 해결책을 찾기 위한 목적을 가진 객체 생성 소프트웨어 디자인 패턴이다. |
| 26 | +
|
| 27 | +그렇긴 하지만, 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)이 무엇인지 조금 더 설명하겠습니다. 어느 시점에서, 우리는 모두 다음과 같은 생성자를 보았습니다. |
| 28 | + |
| 29 | +```java |
| 30 | +public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { |
| 31 | +} |
| 32 | +``` |
| 33 | + |
| 34 | +보시다시피 생성자 매개 변수의 수는 빠르게 감당할 수 없게 되고 매개 변수의 배치를 이해하는 것이 어려워질 수 있습니다. 또한 이 매개 변수 목록은 나중에 더 많은 옵션을 추가하려는 경우 계속 증가할 수 있습니다. 이를 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)이라고 합니다. |
| 35 | + |
| 36 | +**코드 예제** |
| 37 | + |
| 38 | +올바른 대안은 빌더 패턴을 사용하는 것입니다. 우선, 우리는 우리가 창조하고 싶은 영웅을 가지고 있습니다. : |
| 39 | + |
| 40 | + |
| 41 | +```java |
| 42 | +public final class Hero { |
| 43 | + private final Profession profession; |
| 44 | + private final String name; |
| 45 | + private final HairType hairType; |
| 46 | + private final HairColor hairColor; |
| 47 | + private final Armor armor; |
| 48 | + private final Weapon weapon; |
| 49 | + |
| 50 | + private Hero(Builder builder) { |
| 51 | + this.profession = builder.profession; |
| 52 | + this.name = builder.name; |
| 53 | + this.hairColor = builder.hairColor; |
| 54 | + this.hairType = builder.hairType; |
| 55 | + this.weapon = builder.weapon; |
| 56 | + this.armor = builder.armor; |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +그리고 우리는 빌더를 가지고 있습니다. : |
| 62 | + |
| 63 | +```java |
| 64 | + public static class Builder { |
| 65 | + private final Profession profession; |
| 66 | + private final String name; |
| 67 | + private HairType hairType; |
| 68 | + private HairColor hairColor; |
| 69 | + private Armor armor; |
| 70 | + private Weapon weapon; |
| 71 | + |
| 72 | + public Builder(Profession profession, String name) { |
| 73 | + if (profession == null || name == null) { |
| 74 | + throw new IllegalArgumentException("profession and name can not be null"); |
| 75 | + } |
| 76 | + this.profession = profession; |
| 77 | + this.name = name; |
| 78 | + } |
| 79 | + |
| 80 | + public Builder withHairType(HairType hairType) { |
| 81 | + this.hairType = hairType; |
| 82 | + return this; |
| 83 | + } |
| 84 | + |
| 85 | + public Builder withHairColor(HairColor hairColor) { |
| 86 | + this.hairColor = hairColor; |
| 87 | + return this; |
| 88 | + } |
| 89 | + |
| 90 | + public Builder withArmor(Armor armor) { |
| 91 | + this.armor = armor; |
| 92 | + return this; |
| 93 | + } |
| 94 | + |
| 95 | + public Builder withWeapon(Weapon weapon) { |
| 96 | + this.weapon = weapon; |
| 97 | + return this; |
| 98 | + } |
| 99 | + |
| 100 | + public Hero build() { |
| 101 | + return new Hero(this); |
| 102 | + } |
| 103 | + } |
| 104 | +``` |
| 105 | + |
| 106 | +그런 다음, 다음과 같이 사용할 수 있습니다. |
| 107 | + |
| 108 | + |
| 109 | +```java |
| 110 | +var mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build(); |
| 111 | +``` |
| 112 | + |
| 113 | +## 클래스 다이어그램 |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | +## 적용 가능성 |
| 118 | + |
| 119 | +다음과 같은 경우 빌더 패턴을 사용합니다. |
| 120 | + |
| 121 | +* 복잡한 객체를 만드는 알고리즘은 객체를 구성하는 부품과 이들이 조립되는 방법에 독립적이어야 한다. |
| 122 | +* 구축 프로세스는 구성된 객체에 대해 서로 다른 표현을 허용해야 합니다. |
| 123 | + |
| 124 | +## 튜토리얼 |
| 125 | + |
| 126 | +* [Refactoring Guru](https://refactoring.guru/design-patterns/builder) |
| 127 | +* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) |
| 128 | +* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java) |
| 129 | + |
| 130 | +## 실제 사례 |
| 131 | + |
| 132 | +* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html) |
| 133 | +* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on. |
| 134 | +* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-) |
| 135 | +* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html) |
| 136 | +* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder) |
| 137 | +* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html) |
| 138 | + |
| 139 | +## 크레딧 |
| 140 | + |
| 141 | +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) |
| 142 | +* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb) |
| 143 | +* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) |
| 144 | +* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7) |
0 commit comments