λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
  • Dev Blog
CS/λ””μžμΈ νŒ¨ν„΄

[GoF λ””μžμΈ νŒ¨ν„΄] - λΉŒλ” νŒ¨ν„΄

by μœ μ§„μ˜ 2024. 5. 30.
Swift μ½”λ“œκ°€ λ©”μΈμ΄μ§€λ§Œ, λ¬Έλ²•μ˜ 차이둜 인해 μ„€λͺ…에 더 적합할 수 μžˆλŠ” Java μ½”λ“œλ„ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

 

 

λ“±μž₯ λ°°κ²½

λ§Œμ•½ ν”„λ‘œνΌν‹°κ°€ 많고 생성할 λ•Œ κΌ­ ν•„μš”ν•˜μ§€ μ•Šμ€ ν”„λ‘œνΌν‹°, 즉 선택적 ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•œλ‹€κ³  ν•  λ•Œ 객체λ₯Ό μ–΄λ–»κ²Œ 생성해야 ν• κΉŒ? μ΄ˆκΈ°μ—λŠ” μƒμ„±μžλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜μ—¬ λ‹€μ–‘ν•œ 맀개 λ³€μˆ˜μ— λŒ€μ‘ν•  수 μžˆλŠ” 점측적 μƒμ„±μž νŒ¨ν„΄μ΄λΌλŠ” λ°©μ‹μœΌλ‘œ ν•΄κ²°ν•˜μ˜€λ‹€.

 

점측적 μƒμ„±μž νŒ¨ν„΄

 

μ½”λ“œ μ˜ˆμ‹œ

더보기
class Hamburger {
    // ν•„μˆ˜ ν”„λ‘œνΌν‹°
    private int bun;
    private int patty;

    // 선택적 ν”„λ‘œνΌν‹°
    private int cheese = 0;
    private int lettuce = 0;
    private int tomato = 0;
    private int bacon = 0;

    public Hamburger(int bun, int patty, int cheese, int lettuce, int tomato, int bacon) {
        this.bun = bun;
        this.patty = patty;
        this.cheese = cheese;
        this.lettuce = lettuce;
        this.tomato = tomato;
        this.bacon = bacon;
    }

    public Hamburger(int bun, int patty, int cheese, int lettuce, int tomato) {
        this.bun = bun;
        this.patty = patty;
        this.cheese = cheese;
        this.lettuce = lettuce;
        this.tomato = tomato;
    }
    

    public Hamburger(int bun, int patty, int cheese, int lettuce) {
        this.bun = bun;
        this.patty = patty;
        this.cheese = cheese;
        this.lettuce = lettuce;
    }

    public Hamburger(int bun, int patty, int cheese) {
        this.bun = bun;
        this.patty = patty;
        this.cheese = cheese;
    }

    ...
}

public static void main(String[] args) {
    // λͺ¨λ“  μž¬λ£Œκ°€ μžˆλŠ” 햄버거
    Hamburger hamburger1 = new Hamburger(2, 1, 2, 4, 6, 8);

    // λΉ΅κ³Ό νŒ¨ν‹° 치즈만 μžˆλŠ” 햄버거
    Hamburger hamburger2 = new Hamburger(2, 1, 1);

    // λΉ΅κ³Ό νŒ¨ν‹° 베이컨만 μžˆλŠ” 햄버거
    Hamburger hamburger3 = new Hamburger(2, 0, 0, 0, 0, 6); // 0은 ꡳ이 넣어도 λ˜μ§€ μ•ŠλŠ” 데이터
}

 

점측적 μƒμ„±μž νŒ¨ν„΄μ€ μƒμ„±μžμ— ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ„ 경우 λͺ‡ 번째 μΈμžκ°€ μ–΄λ–€ ν”„λ‘œνΌν‹°μ— ν•΄λ‹Ήν•˜λŠ”μ§€ μ•ŒκΈ° μ–΄λ ΅κ³ , 인자 μˆœμ„œμ— 따라야 ν•˜κΈ° λ•Œλ¬Έμ— 선택적 ν”„λ‘œνΌν‹°μ— ν•΄λ‹Ήν•˜λŠ” λ§€κ°œλ³€μˆ˜μ— μ•ˆ 넣어도 될 데이터λ₯Ό μ–΅μ§€λ‘œ λ„£μ–΄μ•Ό ν•˜λŠ” 상황이 μ—°μΆœλœλ‹€.

 

 

μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄

 

μ½”λ“œ μ˜ˆμ‹œ

더보기
class Hamburger {
    // ν•„μˆ˜ ν”„λ‘œνΌν‹°
    private int bun;
    private int patty;

    // 선택적 ν”„λ‘œνΌν‹°
    private int cheese = 0;
    private int lettuce = 0;
    private int tomato = 0;
    private int bacon = 0;
    
    public Hamburger() {}

    public void setBun(int bun) {
        this.bun = bun;
    }

    public void setPatty(int patty) {
        this.patty = patty;
    }

    public void setCheese(int cheese) {
        this.cheese = cheese;
    }

    public void setLettuce(int lettuce) {
        this.lettuce = lettuce;
    }

    public void setTomato(int tomato) {
        this.tomato = tomato;
    }

    public void setBacon(int bacon) {
        this.bacon = bacon;
    }
}

public static void main(String[] args) {
    // λͺ¨λ“  μž¬λ£Œκ°€ μžˆλŠ” 햄버거
    Hamburger hamburger1 = new Hamburger();
    hamburger1.setBun(2);
    hamburger1.setPatty(1);
    hamburger1.setCheese(2);
    hamburger1.setLettuce(4);
    hamburger1.setTomato(6);
    hamburger1.setBacon(8);

    // λΉ΅κ³Ό νŒ¨ν‹° 치즈만 μžˆλŠ” 햄버거
    Hamburger hamburger2 = new Hamburger();
    hamburger2.setBun(2);
    hamburger2.setPatty(1);
    hamburger2.setCheese(2);

    // λΉ΅κ³Ό νŒ¨ν‹° 베이컨만 μžˆλŠ” 햄버거
    Hamburger hamburger3 = new Hamburger();
    hamburger3.setBun(2);
    hamburger2.setPatty(1);
    hamburger3.setBacon(8);
}

 

점측적 μƒμ„±μž νŒ¨ν„΄μ˜ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Setterλ₯Ό μ‚¬μš©ν•œ μžλ°”λΉˆμ¦ˆ(Java Beans) νŒ¨ν„΄μ΄ λ“±μž₯ν•˜μ˜€λ‹€. μ΄λŸ¬ν•œ νŒ¨ν„΄μ΄ λ“±μž₯ν•˜λ©΄μ„œ 가독성 λ¬Έμ œκ°€ ν•΄κ²°λ˜κ³ , setterλ₯Ό ν†΅ν•΄μ„œ μ›ν•˜λŠ” 선택적 ν”„λ‘œνΌν‹°μ—λ§Œ 값을 넣어쀄 수 있게 λ˜μ—ˆλ‹€.

ν•˜μ§€λ§Œ, ν•„μˆ˜ ν”„λ‘œνΌν‹°μ˜ κ°’ 섀정에 λŒ€ν•œ 뢀뢄이 보μž₯λ˜μ§€ μ•Šκ³ , setter λ©”μ„œλ“œκ°€ μ™ΈλΆ€μ μœΌλ‘œ κ³΅κ°œλ˜μ–΄ μžˆμ–΄ 객체의 λΆˆλ³€μ„±μ„ 보μž₯ν•˜μ§€ λͺ»ν•œλ‹€. λ˜ν•œ, 객체가 ν•„μš”ν•œ λͺ¨λ“  데이터λ₯Ό λ°›κΈ° 전에 객체λ₯Ό μ‚¬μš©ν•˜κ²Œ λ˜λŠ” 것을 막을 수 μ—†λ‹€.

 

 

λΉŒλ” νŒ¨ν„΄

λΉŒλ” νŒ¨ν„΄μ€ 점측적 μƒμ„±μž νŒ¨ν„΄κ³Ό μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄μ˜ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ³„λ„μ˜ Builer 객체λ₯Ό μƒμ„±ν•˜κ³  λ©”μ„œλ“œ 체이닝을 ν™œμš©ν•˜μ—¬ μ›ν•˜λŠ” 선택적 ν”„λ‘œνΌν‹°μ˜ 값을 ν• λ‹Ή ν›„ λ§ˆμ§€λ§‰μ— build λ©”μ„œλ“œλ₯Ό 톡해 객체λ₯Ό μƒμ„±ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€.

 

 

μ½”λ“œ μ˜ˆμ‹œ

class HamburgerBuilder {
    // ν•„μˆ˜ ν”„λ‘œνΌν‹°
    private var bun: Int
    private var patty: Int

    // 선택적 ν”„λ‘œνΌν‹°
    private var cheese: Int = 0
    private var lettuce: Int = 0
    private var tomato: Int = 0
    private var bacon: Int = 0

  init(_ bun: Int, _ patty: Int) {
    self.bun = bun
    self.patty = patty
  }

  func cheese(_ cheese: Int) -> HamburgerBuilder {
    self.cheese = cheese
    return self
  }
  
  func lettuce(_ lettuce: Int) -> HamburgerBuilder {
    self.lettuce = lettuce
    return self
  }
  
  func tomato(_ tomato: Int) -> HamburgerBuilder {
    self.tomato = tomato
    return self
  }
  
  func bacon(_ bacon: Int) -> HamburgerBuilder {
    self.bacon = bacon
    return self
  }

  func build() -> Hamburger {
    return Hamburger(bun, patty, cheese, lettuce, tomato, bacon)
  }
}

let hamburger = HamburgerBuilder(2, 1).cheese(2).bacon(1).build()

 

 

μž₯점

 

μ΄ˆκΈ°ν™” λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ„ κ²½μš°μ—λ„ 가독성을 ν•΄μΉ˜μ§€ μ•Šκ³ , ν•„μˆ˜ ν”„λ‘œνΌν‹°μ™€ 선택적 ν”„λ‘œνΌν‹°λ₯Ό 뢄리할 수 μžˆλ‹€.

λ˜ν•œ, ν”„λ‘œνΌν‹° κ°’ 섀정을 μœ„ν•œ λ©”μ„œλ“œκ°€ κ³΅κ°œλ˜μ–΄ μžˆμ–΄λ„ μ–΄λ””κΉŒμ§€λ‚˜ Builder 객체의 ν”„λ‘œνΌν‹°λ₯Ό μ‘°μž‘ν•˜λŠ” 것이지 μ‹€μ œ 객체의 ν”„λ‘œνΌν‹°λ₯Ό μ‘°μž‘ν•˜λŠ” 것이 μ•„λ‹ˆλ―€λ‘œ μ‹€μ œ 객체의 λΆˆλ³€μ„±μ„ 보μž₯ν•  수 μžˆλ‹€. 

λ§ˆμ§€λ§‰μœΌλ‘œ, Builer의 build λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜κΈ° μ „κΉŒμ§€λŠ” μ‹€μ œ 객체가 μƒμ„±λ˜λŠ” 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— μ›ν•˜λŠ” 값을 λ‹€ μ„€μ •ν•΄ μ£ΌκΈ° μ „κΉŒμ§€ 객체 생성을 μ§€μ—°μ‹œν‚¬ 수 μžˆλ‹€.

 

단점

 

μ‹€μ œ 객체λ₯Ό μœ„ν•œ Builder 객체λ₯Ό ν•˜λ‚˜μ”© λ§Œλ“€μ–΄μ•Ό ν•˜λ―€λ‘œ 관리해야 ν•  ν΄λž˜μŠ€κ°€ λ§Žμ•„μ§€κ³  λ³΅μž‘μ„±μ΄ 증가할 수 μžˆλ‹€.

λ˜ν•œ, Builder 객체의 μ½”λ“œκ°€ μž₯ν™©ν•˜κΈ° λ•Œλ¬Έμ— 클래슀의 ν”„λ‘œνΌν‹° κ°œμˆ˜κ°€ 4κ°œλ³΄λ‹€ μ κ±°λ‚˜ κ°œμˆ˜μ— λŒ€ν•œ λ³€κ²½ κ°€λŠ₯성이 μ—†λŠ” κ²½μš°μ—λŠ” μƒμ„±μžλ‚˜ 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜λŠ” 것이 더 μ’‹λ‹€.

 

 

πŸ“Œ Swiftμ—μ„œμ˜ λΉŒλ” νŒ¨ν„΄

 

Swiftμ—μ„œλŠ” λ§€κ°œλ³€μˆ˜ λ ˆμ΄λΈ”μ΄λ‚˜ λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜μ˜ 쑴재둜 인해 λΉŒλ” νŒ¨ν„΄μ˜ ν•„μš”μ„±μ΄ λ‹€λ₯Έ 언어듀에 λΉ„ν•΄ λ–¨μ–΄μ§€λŠ” νŽΈμ΄λ‹€.

λŒ“κΈ€