DevLog πΆ
[μ΄ν©ν°λΈμλ°] μμ΄ν 02. μμ±μμ λ§€κ°λ³μκ° λ§λ€λ©΄ λΉλλ₯Ό κ³ λ €νλΌ λ³Έλ¬Έ
[μ΄ν©ν°λΈμλ°] μμ΄ν 02. μμ±μμ λ§€κ°λ³μκ° λ§λ€λ©΄ λΉλλ₯Ό κ³ λ €νλΌ
dolmeng2 2023. 4. 3. 19:54π¬ μ΄ν©ν°λΈμλ° μμ΄ν 2μ μ½κ³ μ 리ν κΈμ λλ€.

βοΈ ν΄λμ€μ λ©€λ² λ³μκ° λ§μ κ²½μ°, κ°μ²΄λ₯Ό μ΄λ»κ² μμ±ν μ μμκΉ?
- μμ±μλ₯Ό μ¬λ¬ μ’ λ₯λ‘ λμ΄μ, νμν λ§€κ°λ³μλ§μ μ¬μ©νλ μμ±μ μ¬λ¬ κ°λ₯Ό λ§λ€ μ μλ€
- κ·Έλ¬λ, μ΄ λ°©λ²μ νλκ° λμ΄λλ©΄ κ·Έλ§νΌ κ΄λ¦¬ν΄μΌ νλ μμ±μκ° λ§μμ§κΈ° λλ¬Έμ μ’μ§ μλ€.
- λν, λ§€κ°λ³μλ‘ μ λ¬νλ©΄ (μΈν 리μ μ΄μ νλΌλ―Έν° ννΈλ₯Ό μ¬μ©νμ§ μλ μ΄μ) κ° κ°μ μλ―Έλ₯Ό νλμ μμλ³΄κΈ°κ° νλ€κ³ , λ²κ·Έκ° λ°μν νλ₯ μ΄ λμμ§ μ μλ€.
public class Crew {
private String name;
private int age;
private String course;
private String nickname;
}
μμλ‘, ν¬λ£¨μ λν μ 보λ₯Ό λνλ΄λ λ€μκ³Ό κ°μ 4κ°μ§ νλκ° μλ€κ³ κ°μ ν΄λ³΄μ.
π¬ νμν μμ±μλ₯Ό μ λΆ λ§λ€κΈ°
- μ°λ¦¬κ° νμν μμ±μμ λ°λΌ λͺ¨λ μ’ λ₯μ μμ±μλ₯Ό κ°κ° μμ±νλ λ°©λ²μ΄λ€.
public class Crew {
private String name;
private int age;
private String course;
private String nickname;
public Crew(String name, int age) {
this(name, age, "", "");
}
public Crew(String name, String nickname, int age) {
this(name, age, "", nickname);
}
public Crew(final String name, final int age, final String course, final String nickname) {
this.name = name;
this.age = age;
this.course = course;
this.nickname = nickname;
}
}
μ΄ λ°©λ²μμ ν° νΉμ§μ, λ§€κ°λ³μκ° μ μ μμ±μλ λ§€κ°λ³μκ° λ§μ μμ±μλ₯Ό μ μ§μ μΌλ‘ νΈμΆνλ€λ κ²μ΄λ€.
μ΄λ κ² λλ©΄ μ΄κΈ°κ°μ μ€μ ν΄λκΈ° λλ¬Έμ λΆλ³ κ°μ²΄λ‘ μμ±ν μ μμ§λ§, μμ±μμ κ°μκ° νλμ λ°λΌμ κ³μ μ¦κ°νλ€λ λ¨μ μ΄ μκ³ , μκ·Έλμ²λ₯Ό κ°μ§ λ§€κ°λ³μμ κ²½μ° λ¨μ μμ±μλ‘μλ μμ±ν μ μλ€λ λ¨μ μ΄ μ‘΄μ¬νλ€.
π¬ μλ°λΉμ¦ ν¨ν΄
- λ§€κ°λ³μκ° μλ μμ±μλ‘ κ°μ²΄λ₯Ό μμ±νκ³ , setterλ₯Ό ν΅ν΄μ κ° λ³μμ κ°μ μΈν νλ λ°©μμ΄λ€.
public class Crew {
private String name;
private int age;
private String course;
private String nickname;
public void setName(final String name) {
this.name = name;
}
public void setAge(final int age) {
this.age = age;
}
public void setCourse(final String course) {
this.course = course;
}
public void setNickname(final String nickname) {
this.nickname = nickname;
}
}
- κ·Έλ¬λ, μ΄ λ°©λ²μ κ°μ²΄ νλλ₯Ό λ§λ€κΈ° μν΄ μ¬λ¬ κ°μ λ©μλλ₯Ό νΈμΆν΄μΌ λλ©°, setterλ₯Ό μ΄μ΄λκ² λλ€λ©΄ κ°μ²΄μ λν λ³κ²½ κ°λ₯μ±μ μ΄μ΄λμ΄ λΆλ³ν¨μ λ§λ€ μκ° μμ΄μ§λ€.
- λν, κ°λ°μκ° λͺ μμ μΌλ‘ setterλ₯Ό νμ©νμ¬ κ°μ λ£μ΄μ£Όμ΄μΌ νκΈ° λλ¬Έμ, setterλ₯Ό νΈμΆνκΈ° μ κΉμ§ ν΄λΉ κ°μ²΄λ λΆμμ ν μνκ° λλ€. : μλΉν μννλ€. NPEμ κ°λ₯μ±μ μ΄μ΄λλ κ²μ΄λ©°, κ°μ²΄μ λΆλ³μ±μ ν΄μΉκΈ° λλ¬Έμ μ€λ₯ κ°λ₯μ±λ λμμ§λ€.
π¬ λΉλ ν¨ν΄
- νμ λ§€κ°λ³μλ‘ μμ±μλ₯Ό νΈμΆνμ¬ λΉλ κ°μ²΄λ₯Ό μ»κ³ , λΉλ κ°μ²΄μ setterλ₯Ό ν΅ν΄ μ ν λ§€κ°λ³μλ₯Ό μ€μ νλ λ°©λ²μ΄λ€.
- μ΄ν, buildλ₯Ό ν΅ν΄μ λΆλ³ κ°μ²΄λ₯Ό λ§λλ λ°©λ²μ΄λ€.
public class Crew {
private String name;
private int age;
private String course;
private String nickname;
public static class Builder {
// νμ λ§€κ°λ³μ
private final String name;
private final String nickname;
// μ ν λ§€κ°λ³μλ κΈ°λ³Έκ°μΌλ‘ μ΄κΈ°ννκΈ°
private int age = 0;
private String course = "";
// νμ κ° μμ±μ
public Builder (String name, String nickname) {
this.name = name;
this.nickname = nickname;
}
// μ ν κ° μ£Όμ
public Builder age(int age) {
this.age = age;
return this;
}
public Builder course(int age) {
this.course = age;
return this;
}
// κ°μ²΄ μμ±νκΈ°
public void build() {
return new Crew(this);
}
}
private Crew(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.course = builder.course;
this.nickname = builder.nickname;
}
}
κ°μ²΄λ λ€μκ³Ό κ°μ μμλ‘ μμ±ν μ μλ€.
1. νμν κ°μ²΄μ λ΄λΆ Builder ν΄λμ€μ μμ±μλ₯Ό νΈμΆνμ¬, Builder κ°μ²΄λ₯Ό μ»λλ€. (νμ λ§€κ°λ³μ λ°κΈ°)
2. Builder κ°μ²΄μ setterλ₯Ό νμ©νμ¬ μ ν λ§€κ°λ³μμ κ°μ ν λΉνλ€.
3. build()λ₯Ό νΈμΆνμ¬ μ΅μ’ μ μΌλ‘ νμν κ°μ²΄λ₯Ό μ»λλ€.
μ μ½λλ Crewμ μμ±μκ° privateμΌλ‘ λ§ν μκ³ , Crewμ λν λΆλ³μ±μ 보μ₯ν μ μλ€. (μμ±μλ₯Ό ν΅ν΄ λ§λ€κΈ° λλ¬Έμ)
- μ΄λ, μΆκ°μ μΌλ‘ κ²μ¦ λ‘μ§μ΄ λ€μ΄κ°λ€λ©΄ buildκ° νΈμΆνλ μμ±μμμ κ²μ¬νλ κ²μ΄ μ’λ€. (νΉμ builderμ μμ±μ)
- λν, λΉλμ setter λ©μλλ€μ΄ return this;λ₯Ό ν΅ν΄μ μκΈ° μμ (=Builder)λ₯Ό λ°ννκΈ° λλ¬Έμ, λ λ€μ λ©μλλ₯Ό μ°μμ μΌλ‘ νΈμΆμ΄ κ°λ₯νκ² λλ€.
ν΄λΌμ΄μΈνΈμ μ½λλ‘ λ³Έλ€λ©΄ λ€μκ³Ό κ°μ΄ μ¬μ©ν μ μκ² λλ κ²μ΄λ€.
Crew crew = new Crew
.Builder(βμ΄λ¦β, βλλ€μβ)
.age(23)
.course(βλ°±μλβ)
.build();
μ΄λ κ² λλ©΄, ν΄λΌμ΄μΈνΈλ λ΄λΆμ νμν κ°κ°μ κ°λ€μ΄ 무μμ μλ―Ένλμ§ νμ νκΈ°λ μ¬μμ§λ€.
βοΈ μ΄λ»κ² νμ©νλ©΄ μ’μκΉ?
λν, κ³μΈ΅μ μΌλ‘ μ€κ³λ ν΄λμ€μ κ°μ΄ μ¬μ©νλ κ²λ μ’λ€.
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
public abstract class ConvenientStore {
public enum Brand {CU, GS, SEVEN_ELEVEN, MINI_STOP}
final Set<Brand> brands;
abstract static class Builder<T extends Builder<T>> {
EnumSet<Brand> brands = EnumSet.noneOf(Brand.class);
public T addBrand(Brand brand) {
brands.add(Objects.requireNonNull(brand));
return self();
}
abstract ConvenientStore build();
protected abstract T self();
}
ConvenientStore(Builder<?> builder) {
brands = builder.brands.clone();
}
}
κ°λ¨ν μμλ₯Ό λ€μ΄λ³΄μ. νΈμμ μ λν μΆμν΄λμ€λ₯Ό μμ±ν λ€μ, λΈλλμ λν enum νμ μ μ μνμλ€.
μ μ½λμ νΉμ§μ λ€μ΄λ³΄μλ©΄ λ€μκ³Ό κ°λ€.
1. μΆμ ν΄λμ€λ‘ μ μΈμ΄ λμ΄ μκΈ° λλ¬Έμ , μ§μ μ μΌλ‘ μΈμ€ν΄μ€νκ° λΆκ°λ₯νλ€.
2. μ λ€λ¦ νμ μΈ Tκ° μ¬μ©λμ΄ μμΌλ©°, μ¬κΈ°μ Tλ Builder ν΄λμ€λ₯Ό μμλ°μ ν΄λμ€μ νμ μ΄λ€.
3. brandsμ κ²½μ° EnumSet<Brand> νμ μΌλ‘, BrandλΌλ enum νμ μ κ°μ λ΄λλ€.
4. addBrandλ Brand νμ μ κ°μ μΈμλ‘ λ°μμ brandsμ μΆκ°νλ©°, self()λ₯Ό ν΅ν΄ Builder ν΄λμ€λ₯Ό μμλ°μ ꡬνν ν΄λμ€μμ ꡬνλ λ©μλμ λ°νκ°μ΄ 리ν΄λλ€.
π¬ μ¬κ·μ νμ νμ
μ¬κΈ°μ μ°μΈ Builder<T extends Builder<T>>λ μ¬κ·μ νμ νμ μ΄λΌκ³ νλ€.
νμ λ§€κ°λ³μ Tκ° μμ μ νμ μ ν¬ν¨νλ μμ λͺ¨λμ νμ λλ κ²μ μλ―Ένλ€.
-> Tκ° μμ μ ν¬ν¨νλ μμμΈ Builder<T>μ μν΄ νμ (extends)λλ€.
: λ§μ΄ μ΄λ ΅μ§λ§, μ½κ² μκ°νλ©΄ Tλ Builder ν΄λμ€λ₯Όμμλ°μ ν΄λμ€μμ μλ―Ένλ€λ λ»μ΄λ€.
μ μ¬μ©νλ κ±ΈκΉ?
class Builder<T extends Builder<T>> {
...
}
μ΄λ κ² λλ©΄ Builder ν΄λμ€λ₯Ό μμλ°μ ν΄λμ€μμ, ν΄λΉ ν΄λμ€μ νμ μ μ μν λ
μκΈ° μμ μ νμ μ μ 곡νλ©΄μ Builder ν΄λμ€μ λ©μλλ ν¨κ» μ¬μ©ν μ μκ² λλ€.
public static class Builder extends ConvenientStore.Builder<Builder> {
...
}
μλ₯Ό λ€μ΄, μ¬κΈ°μ ConvenientStore.Builder ν΄λμ€λ Builder<ConvenientStore.Builder> νμ μ΄λ©°, Tλ Builder<ConvenientStore.Builder> κ° λλ κ²μ΄κΈ° λλ¬Έμ Builder ν΄λμ€μ λ©μλλ₯Ό μ¬μ©ν μ μκ² λλ€.
κ·Έλ κΈ° λλ¬Έμ, μμμ μ μΈνλ addBrand(), build() λ©μλλ ConvenientStore.Builderμμλ μ¬μ©ν μ μκ² λλ€.
λ€μ λμμμ, νΈμμ μ΄ νμ₯νμ¬ μΈκ΅μΌλ‘ νμ₯νλ€κ³ κ°μ ν΄λ³΄μ.
μ΄λ, μΌλ³Έ νΈμμ μ νλΌλ―Έν°λ‘ λ§€μ₯μ μ μ μλ₯Ό λ°λλ€λ©΄?
public class JapanConvenientStore extends ConvenientStore {
public final int employeesCount;
public static class Builder extends ConvenientStore.Builder<Builder> {
private int employeesCount = 0;
public Builder updateEmployeesCount(int employeeCount) {
this.employeesCount = employeeCount;
return this;
}
@Override
public JapanConvenientStore build() {
return new JapanConvenientStore(this);
}
@Override
protected Builder self() {
return this;
}
}
private JapanConvenientStore(Builder builder) {
super(builder);
employeesCount = builder.employeesCount;
}
}
νμ ν΄λμ€μ build λ©μλλ ꡬ체 νμ ν΄λμ€λ₯Ό λ°ννλλ‘ μ μΈνλ€.
-> μ΄λ° μμΌλ‘ νμ ν΄λμ€μ λ©μλ(build)κ° μμ ν΄λμ€μ λ©μλκ° μ μν λ°ν νμ λμ , νμ νμ (JapanConvenientStore)μ λ°ννλ κ²μ βκ³΅λ³ λ°ν νμ΄νβμ΄λΌκ³ νλ€.
= λΆλͺ¨ ν΄λμ€μ λ©μλλ₯Ό μ€λ²λΌμ΄λ© ν λ, λΆλͺ¨ ν΄λμ€μ λ°ν νμ μ μμ ν΄λμ€μ νμ μΌλ‘ λ³κ²½νλ κ².
μ΄λ₯Ό μ¬μ©νκ² λλ©΄, ν΄λΌμ΄μΈνΈλ ν λ³νμ μ κ²½μ°μ§ μκ³ λΉλλ₯Ό μ¬μ©ν μ μκ² λλ€.
λν, self()λ μμ μ μΈμ€ν΄μ€λ₯Ό λ°ννκ³ μλ κ²μ λ³Ό μ μλ€.
public T addBrand(Brand brand) {
brands.add(Objects.requireNonNull(brand));
return self();
}
λ°ν νμ μΈ Tλ μ¬κ·μ νμ νμ μ μν΄μ μκΈ° μμ μ ꡬνν νμ ν΄λμ€μΈλ°,
νμ ν΄λμ€μ self()μμ thisλ₯Ό λ°ννμ¬ μμ ν΄λμ€μμ νμ ν΄λμ€λ₯Ό λ°νν μ μλλ‘ λ§λ€μλ€.
μ무νΌ, μ΄ λλΆμ ν΄λΌμ΄μΈνΈλ μ΄λ¬ν λΉλ ν¨ν΄μ νμ©νμ¬ λ€μκ³Ό κ°μ΄ μ μΈμ΄ κ°λ₯νλ€.
JapanConvenientStore store = new JapanConvenientStore
.Builder()
.addBrand(ConvenientStore.Brand.LAWSON)
.build();
μ΄λ° μμΌλ‘ μνλ λ§€κ°λ³μλ₯Ό νμ©νμ¬ κ°μ²΄λ₯Ό μμ±ν μ μλ€λ μ₯μ μ΄ μλ€.
κ·Έλ¬λ, μ΄ ν¨ν΄μ μμ± λΉμ©μ κ³ λ €ν΄μΌ νλ©°, λ§€κ°λ³μκ° λ§μ κ²½μ° λ μ λμνλ€.
λ³΄ν΅ νλ‘κ·Έλ¨μ΄ 컀μ§μλ‘ λ§€κ°λ³μκ° μ»€μ§λ κ²½μ°κ° λ§κΈ° λλ¬Έμ, μμ±μμ μ μ ν©ν°λ¦¬κ° μ²λ¦¬ν λ§€κ°λ³μκ° λ§μ κ²½μ° μ²μλΆν° λΉλ ν¨ν΄μ μ ννλ κ² λμ μ μλ€.
+ λ§μ½, μ¬κ·μ νμ νμ μ μ¬μ©νμ§ μμμ κ²½μ° μ΄λ»κ² λ κΉ?
=public abstract class ConvenientStore {
public enum Brand {CU, GS, SEVEN_ELEVEN, MINI_STOP, LAWSON}
final Set<Brand> brands;
abstract static class Builder {
EnumSet<Brand> brands = EnumSet.noneOf(Brand.class);
public Builder addBrand(Brand brand) {
brands.add(Objects.requireNonNull(brand));
return self();
}
abstract ConvenientStore build();
protected abstract Builder self();
}
ConvenientStore(Builder builder) {
brands = builder.brands.clone();
}
}
public class JapanConvenientStore extends ConvenientStore {
public final int employeesCount;
public static class Builder extends ConvenientStore.Builder {
private int employeesCount = 0;
public Builder updateEmployeesCount(int employeeCount) {
this.employeesCount = employeeCount;
return this;
}
@Override
public JapanConvenientStore build() {
return new JapanConvenientStore(this);
}
@Override
protected Builder self() {
return this;
}
}
private JapanConvenientStore(Builder builder) {
super(builder);
employeesCount = builder.employeesCount;
}
}
μ΄λ° μμΌλ‘ μ½λκ° μμ±λ ν λ°, κ·ΈλΌ ν΄λΌμ΄μΈνΈ μΈ‘μμ λͺ μμ μΌλ‘ νλ³νμ ν΄μ€μΌ νλ€.
JapanConvenientStore store = (JapanConvenientStore) new JapanConvenientStore
.Builder()
.addBrand(ConvenientStore.Brand.LAWSON)
.build();