# Factory Pattern (1) Factory Method Pattern

Assembled by GimunLee

# Goal

  • Factory Pattern의 κ°œλ…μ„ μ•Œ 수 μžˆλ‹€.
  • Simple Factory와 Factory Method Pattern의 차이점에 λŒ€ν•΄ μ„€λͺ…ν•  수 μžˆλ‹€.
  • Factory Method Pattern의 μ‚¬μš© 이점에 λŒ€ν•΄ μ„€λͺ…ν•  수 μžˆλ‹€.

# ν”Όμž κ°€κ²Œ 차리기

μ—¬λŸ¬λΆ„μ΄ ν”Όμž κ°€κ²Œλ₯Ό μš΄μ˜ν•˜κ³  있고, κ°μ²΄λ§ˆμ„μ˜ μ΅œμ²¨λ‹¨ ν”Όμž κ°€κ²Œ μ£ΌμΈλ‹΅κ²Œ λ‹€μŒκ³Ό 같은 μ½”λ“œλ₯Ό λ§Œλ“€μ—ˆλ‹€κ³  κ°€μ •ν•΄ λ΄…μ‹œλ‹€.

Pizza orderPizza(String type) { // ν”Όμž μ’…λ₯˜ 전달
    Pizza pizza;

    if(type.equals("cheese")){
        pizza = new CheesePizza();
    }else if(type.equals("greek")){
        pizza = new GreekPizza();
    }else if(type.equals("pepperoni")){
        pizza = new PepperoniPizza();
    }

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();

    return pizza;
}

ν”Όμž κ°€κ²Œμ—μ„œ 쑰개 ν”Όμž(Clam Pizza)ν•˜κ³  야채 ν”Όμž(Veggie Pizza)λ₯Ό 메뉴에 μΆ”κ°€ν•˜κΈ°λ‘œ ν–ˆμŠ΅λ‹ˆλ‹€. 그리고 κ·Έλ¦¬μŠ€μ‹(Greek Pizza)κ°€ λ³„λ‘œ μ•ˆ νŒ”λ €μ„œ λ©”λ‰΄μ—μ„œ μ œμ™Έμ‹œν‚€κΈ°λ‘œ ν–ˆμŠ΅λ‹ˆλ‹€.

Pizza orderPizza(String type) { // ν”Όμž μ’…λ₯˜ 전달
    Pizza pizza;

    if(type.equals("cheese")){
        pizza = new CheesePizza();
    }
    // else if(type.equals("greek")){
    //    pizza = new GreekPizza();
    // }
    else if(type.equals("pepperoni")){
        pizza = new PepperoniPizza();
    }else if(type.equals("clam")){
        pizza = new ClamPizza();
    }else if(type.equals("veggie")){
        pizza = new veggiePizza();
    }
    // 메뉴가 변경될 λ•Œ λ§ˆλ‹€ μœ„ μ½”λ“œλŠ” 계속 변경돼야함

    // 이 λ°‘ 뢀뢄은 λ³€κ²½λ˜μ§€ μ•ŠμŒ
    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();

    return pizza;
}

orderPizza() λ©”μ†Œλ“œμ—μ„œ κ°€μž₯ λ¬Έμ œκ°€ λ˜λŠ” 뢀뢄은 λ°”λ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ ꡬ상 클래슀λ₯Ό μ„ νƒν•˜λŠ” λΆ€λΆ„μž…λ‹ˆλ‹€. κ·Έ λΆ€λΆ„ λ•Œλ¬Έμ— 상황에 따라 μ½”λ“œλ₯Ό λ³€κ²½ν•  수 밖에 μ—†μŠ΅λ‹ˆλ‹€. 이제 μ–΄λ–€ 뢀뢄이 λ°”λ€Œκ³  μ–΄λ–€ 뢀뢄이 λ°”λ€Œμ§€ μ•ŠλŠ”μ§€λ₯Ό νŒŒμ•…ν–ˆμœΌλ‹ˆ μΊ‘μŠν™”λ₯Ό ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.


# 객체 생성 μΊ‘μŠν™”

객체 생성 μ½”λ“œλ§Œ λ”°λ‘œ λΉΌμ„œ ν”Όμž 객체λ₯Ό λ§Œλ“œλŠ” 일만 μ „λ‹΄ν•˜λŠ” λ‹€λ₯Έ 객체에 집어넣어 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

μƒˆλ‘œ λ§Œλ“€ κ°μ²΄μ—λŠ” νŒ©ν† λ¦¬(FactoryλΌλŠ” 이름을 λΆ™μ΄κΈ°λ‘œ ν•©μ‹œλ‹€.

객체 생성을 μ²˜λ¦¬ν•˜λŠ” 클래슀λ₯Ό νŒ©ν† λ¦¬λΌκ³  λΆ€λ¦…λ‹ˆλ‹€. 일단 SimplePizzaFactoryλ₯Ό λ§Œλ“€κ³  λ‚˜λ©΄ orderPizza() λ©”μ†Œλ“œλŠ” μƒˆλ‘œ λ§Œλ“  객체의 ν΄λΌμ΄μ–ΈνŠΈκ°€ λ©λ‹ˆλ‹€. 즉 μƒˆλ‘œ λ§Œλ“  객체λ₯Ό ν˜ΈμΆœν•˜λŠ” κ±°μ£ . ν”Όμžκ°€ ν•„μš”ν•  λ•Œ λ§ˆλ‹€ ν”Όμž 곡μž₯에 ν”Όμž ν•˜λ‚˜ λ§Œλ“€μ–΄ 달라고 λΆ€νƒν•œλ‹€κ³  μƒκ°ν•˜λ©΄ λ©λ‹ˆλ‹€. 이제 더 이상 orderPizza() λ©”μ†Œλ“œμ—μ„œ μ–΄λ–€ ν”Όμžλ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜λŠ”μ§€ κ³ λ―Όν•˜μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€. orderPizza() λ©”μ†Œλ“œμ—μ„œλŠ” Pizza μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” ν”Όμžλ₯Ό λ°›μ•„μ„œ κ·Έ μΈν„°νŽ˜μ΄μŠ€μ—μ„œ μ •μ˜ν–ˆλ˜ prepare(), bake(), cut(), box() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.


# κ°„λ‹¨ν•œ ν”Όμž νŒ©ν† λ¦¬ λ§Œλ“€κΈ°

μƒˆλ‘œ λ§Œλ“€ SimplePizzaFactory ν΄λž˜μŠ€μ—μ„œ ν•˜λŠ” 일은 ν•˜λ‚˜ λΏμž…λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μœ„ν•΄μ„œ ν”Όμžλ₯Ό λ§Œλ“€μ–΄μ£ΌκΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

public class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;

        if(type.equals("cheese")) {
            pizza = new CheesePizza();
        }else if(type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }else if(type.equals("clam")){
            pizza = new ClamPizza();
        }else if(type.equals("veggie")){
            pizza = new VeggiePizza();
        }
        return pizza();
    }
}

# 바보같은 μ§ˆλ¬Έμ€ μ—†μŠ΅λ‹ˆλ‹€.

# μ΄λ ‡κ²Œ ν•˜λ©΄ 무슨 μž₯점이 μžˆλŠ” κ±΄κ°€μš”? μ•„κΉŒ κ·Έ 문제λ₯Ό κ·Έλƒ₯ λ‹€λ₯Έ 객체둜 λ„˜κ²¨ 버렸을 뿐인 것 κ°™μ€λ°μš”?

SimplePizzaFactoryλ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ 맀우 λ§Žμ„ 수 μžˆλ‹€λŠ” 점을 생각해 λ³΄μ„Έμš”. μ—¬κΈ°μ—λŠ” orderPizza() λ©”μ†Œλ“œλ§Œ λ‚˜μ™€ μžˆμ§€λ§Œ, ν”Όμž 객체λ₯Ό λ°›μ•„μ„œ 가격이라든가 ν”Όμžμ— λŒ€ν•œ μ„€λͺ… 등을 μ°Ύμ•„μ„œ ν™œμš©ν•˜λŠ” PizzaShopMenu 같은 ν΄λž˜μŠ€λΌλ“ κ°€, μ•„κΉŒ 봀던 PizzaStore ν΄λž˜μŠ€μ—μ„œ ν–ˆλ˜ κ²ƒκ³ΌλŠ” 쑰금 λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ ν”Όμž 주문을 μ²˜λ¦¬ν•˜λŠ” HomeDelivery 같은 ν΄λž˜μŠ€μ—μ„œλ„ 이 νŒ©ν† λ¦¬λ₯Ό μ‚¬μš©ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

# λΉ„μŠ·ν•œ 식을 νŒ©ν† λ¦¬λ₯Ό μ“°λŠ”λ°, λ©”μ†Œλ“œλ₯Ό 정적 λ©”μ†Œλ“œλ‘œ μ„ μ–Έν•œ λ””μžμΈμ„ λ³Έ 적이 μžˆμ–΄μš”. κ·Έ λ””μžμΈμ΄λž‘ 이 λ””μžμΈμ€ μ–΄λ–»κ²Œ λ‹€λ₯Έκ±°μ£ ?

κ°„λ‹¨ν•œ νŒ©ν† λ¦¬λ₯Ό 정적 λ©”μ†Œλ“œλ‘œ μ •μ˜ν•˜λŠ” 기법도 일반적으둜 많이 μ“°μž…λ‹ˆλ‹€. 정적 νŒ©ν† λ¦¬(static factory)라고 λΆ€λ₯΄κΈ°λ„ ν•˜μ£ . μ™œ 정적 λ©”μ†Œλ“œλ₯Ό μ“°λŠ”μ§€ κΆκΈˆν•˜μ£ ? 정적 λ©”μ†Œλ“œλ₯Ό μ“°λ©΄ 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œν‚€κΈ° μœ„ν•΄μ„œ 객체의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ§€ μ•Šμ•„λ„ 되기 λ•Œλ¬Έμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€μ–΄μ„œ 객체 생성 λ©”μ†Œλ“œμ˜ 행동을 λ³€κ²½μ‹œν‚¬ 수 μ—†λ‹€λŠ” 단점이 μžˆλ‹€λŠ” 것도 κΌ­ κΈ°μ–΅ν•΄λ‘μ„Έμš”.

이제 ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό κ³ μ³λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class PizzaStore {
    SimplePizzaFactory factory;

    public PizzaStore (SimplePizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza orderPizza(String type){
        Pizza pizza;

        pizza = factory.createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
}

κ°„λ‹¨ν•œ νŒ©ν† λ¦¬(Simple Factory)λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λΌκ³  ν•  μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€. ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜λŠ”λ° μžˆμ–΄μ„œ 자주 μ“°μ΄λŠ” κ΄€μš©κ΅¬μ— 가깝닀고 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μœ„μ—μ„œ λ§Œλ“  ν”Όμž κ°€κ²Œ ν”„λ‘œκ·Έλž¨μ˜ 클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ„ ν•œλ²ˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

κ°„λ‹¨ν•œ νŒ©ν† λ¦¬λŠ” μ›Œλ°μ—…μ΄λΌκ³  μƒκ°ν•©μ‹œλ‹€. μ΄μ œλΆ€ν„° νŒ©ν† λ¦¬μ— ν•΄λ‹Ήν•˜λŠ” 두 가지 κ°•λ ₯ν•œ νŒ¨ν„΄μ„ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.


# ν”Όμž ν”„λ Œμ°¨μ΄μ¦ˆ 사업

ν”„λ Œμ°¨μ΄μ¦ˆλ₯Ό μš΄μ˜ν•˜κ²Œ λμŠ΅λ‹ˆλ‹€. μ§€κΈˆκΉŒμ§€ 잘 μ¨μ™”λ˜ μ½”λ“œλ₯Ό λ‹€λ₯Έ μ§€μ μ—μ„œλ„ μ“Έ 수 μžˆλ„λ‘ λ§Œλ“€κΈ°λ‘œ ν–ˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ§€μ—­λ³„λ‘œ μ‘°κΈˆμ”© λ‹€λ₯Έ 차이점을 μ–΄λ–€ μ‹μœΌλ‘œ μ μš©ν•΄μ•Ό ν• κΉŒμš”? 각 μ§€μ λ§ˆλ‹€ κ·Έ μ§€μ—­μ˜ νŠΉμ„±κ³Ό μž…λ§›μ„ λ°˜μ˜ν•˜μ—¬ λ‹€λ₯Έ μŠ€νƒ€μΌμ˜ ν”Όμž(뉴μ˜₯ μŠ€νƒ€μΌ, μ‹œμΉ΄κ³  μŠ€νƒ€μΌ, μΊ˜λ¦¬ν¬λ‹ˆμ•„ μŠ€νƒ€μΌ)λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

SimplePizzaFactoryλ₯Ό λΉΌκ³  μ„Έ 가지 μ„œλ‘œ λ‹€λ₯Έ νŒ©ν† λ¦¬(NYPizzaFactory, ChicagoPizzaFactory, CaliforniaPizzaFactory)λ₯Ό λ§Œλ“  λ‹€μŒ, PizzaStoreμ—μ„œ μ λ‹Ήν•œ νŒ©ν† λ¦¬λ₯Ό μ‚¬μš©ν•˜λ„λ‘ ν•˜λ©΄ λΆ„μ μ—μ„œλ„ μ „ν˜€ 문제 없이 μ“Έ 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

κ·Έ 방법을 μ μš©ν•˜λ©΄ μ–΄λ–»κ²Œ 될지 ν•œλ²ˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

뉴μ˜₯ 뢄점

NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.order("Veggie");

μ‹œμΉ΄κ³  뢄점

ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.order("Veggie");

방금 μ–˜κΈ°ν•œ 방법을 직접 μ μš©ν•΄ λ΄€μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ, λ³Έμ μ—μ„œ μš°λ¦¬κ°€ λ§Œλ“  νŒ©ν† λ¦¬λ₯Ό μ¨μ„œ ν”Όμžλ₯Ό λ§Œλ“€κΈ΄ ν•˜λŠ”λ°, λ…μžμ μΈ 방법듀을 μ‚¬μš©ν•˜κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€. κ΅½λŠ” 방식이 λ‹¬λΌμ§„λ‹€κ±°λ‚˜ μ’…μ’… ν”Όμžλ₯Ό 자λ₯΄λŠ” 것을 κΉŒλ¨Ήμ–΄ λ²„λ¦¬λŠ” 일이 μΌμ–΄λ‚˜κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€.

이 문제λ₯Ό λ‹€μ‹œ ν•œλ²ˆ μƒκ°ν•΄λ³΄λ‹ˆ, ν”Όμž κ°€κ²Œμ™€ ν”Όμž μ œμž‘ κ³Όμ • 전체λ₯Ό ν•˜λ‚˜λ‘œ λ¬Άμ–΄μ£ΌλŠ” ν”„λ ˆμž„μ›Œν¬λ₯Ό λ§Œλ“€μ–΄μ•Ό λ˜κ² λ‹€λŠ” 결둠에 λ„λ‹¬ν–ˆμŠ΅λ‹ˆλ‹€. λ¬Όλ‘  κ·Έλ ‡κ²Œ ν•˜λ©΄μ„œλ„ μœ μ—°μ„±μ„ μžƒμ–΄λ²„λ¦¬λ©΄ μ•ˆ 되겠죠.

SimplePizzaFactoryλ₯Ό λ§Œλ“€κΈ° 전에 썼던 μ½”λ“œμ—μ„œλŠ” ν”Όμžλ₯Ό λ§Œλ“œλŠ” μ½”λ“œκ°€ PizzaStoreν•˜κ³  직접 μ—°κ²°λ˜μ–΄ 있긴 ν–ˆμ—ˆμ§€λ§Œ, μœ μ—°μ„±μ΄ μ „ν˜€ μ—†μ—ˆμŠ΅λ‹ˆλ‹€.

그러면 μ–΄λ–»κ²Œ ν•΄μ•Ό ν”Όμž κ°€κ²Œν•˜κ³  ν”Όμž λ§Œλ“œλŠ” 과정을 ν•˜λ‚˜λ‘œ 묢을 수 μžˆμ„κΉŒμš”?


# ν”Όμž κ°€κ²Œ ν”„λ ˆμž„μ›Œν¬

ν”Όμžλ₯Ό λ§Œλ“œλŠ” 할동 μžμ²΄λŠ” μ „λΆ€ PizzaStore ν΄λž˜μŠ€μ— κ΅­ν•œμ‹œν‚€λ©΄μ„œλ„ λΆ„μ λ§ˆλ‹€ 고유의 μŠ€νƒ€μΌμ„ 살릴 수 μžˆλ„λ‘ ν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€.

이제 createPizza() λ©”μ†Œλ“œλ₯Ό PizzaStore에 λ‹€μ‹œ μ§‘μ–΄λ„£κ² μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ΄λ²ˆμ—λŠ” κ·Έ λ©”μ†Œλ“œλ₯Ό 좔상 λ©”μ†Œλ“œ 둜 μ„ μ–Έν•˜κ³ , 각 μ§€μ—­λ§ˆλ‹€ 고유의 μŠ€νƒ€μΌμ— 맞게 PizzaStore의 μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€λ„λ‘ ν•  κ²ƒμž…λ‹ˆλ‹€.

μš°μ„  PizzaStoreκ°€ μ–΄λ–»κ²Œ λ‹¬λΌμ§€λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public abstract class PizzaStore {
    public Pizza orderPizza(String type){
        Pizza pizza;

        pizza = createPizza(type); // νŒ©ν† λ¦¬ 객체가 μ•„λ‹Œ PizzaStore에 μžˆλŠ” λ©”μ†Œλ“œ 호좜

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }

    abstract Pizza createPizza(String type); // νŒ©ν† λ¦¬ 객체 λŒ€μ‹  이 λ©”μ†Œλ“œ μ‚¬μš©
}

각 뢄점을 μœ„ν•œ μ„œλΈŒν΄λž˜μŠ€κ°€ ν•„μš”ν•©λ‹ˆλ‹€. 이제 각 μ§€μ—­λ³„λ‘œ μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. ν”Όμžμ˜ μŠ€νƒ€μΌμ€ 각 μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ²°μ •ν•©λ‹ˆλ‹€. μ–΄λ–€ μ‹μœΌλ‘œ λŒμ•„κ°€λŠ”μ§€ μ‚΄νŽ΄λ΄…μ‹œλ‹€.

# μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ²°μ •λ˜λŠ” 것

PizzaStore의 orderPizza() λ©”μ†Œλ“œμ— 이미 μ£Όλ¬Έ μ‹œμŠ€ν…œμ΄ 잘 κ°–μΆ°μ Έ μžˆμŠ΅λ‹ˆλ‹€. 이 μ£Όλ¬Έ μ‹œμŠ€ν…œ μžμ²΄λŠ” λͺ¨λ“  λΆ„μ μ—μ„œ λ˜‘κ°™μ΄ μ§„ν–‰λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

각 λΆ„μ λ§ˆλ‹€ λ‹¬λΌμ§ˆ 수 μžˆλŠ” 것은 ν”Όμžμ˜ μŠ€νƒ€μΌ λΏμž…λ‹ˆλ‹€. 뉴μ˜₯풍 ν”ΌμžλŠ” 빡이 μ–‡κ³ , μ‹œμΉ΄κ³  풍 ν”ΌμžλŠ” 빡이 λ‘κΊΌμš΄ μ‹μœΌλ‘œ 말이죠. μ΄λ ‡κ²Œ λ‹¬λΌμ§€λŠ” 점듀은 createPizza() λ©”μ†Œλ“œμ— 집어넣고 κ·Έ λ©”μ†Œλ“œμ—μ„œ ν•΄λ‹Ή μŠ€νƒ€μΌμ˜ ν”Όμžλ₯Ό λ§Œλ“œλŠ” 것을 λͺ¨λ‘ μ±…μž„μ§€λ„λ‘ ν•  κ³„νšμž…λ‹ˆλ‹€. PizzaStore의 μ„œλΈŒν΄λž˜μŠ€μ—μ„œ createPizza() λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ ν•˜λ©΄ 되죠. 이제 PizzaStore ν”„λ ˆμž„μ›Œν¬μ— μΆ©μ‹€ν•˜λ©΄μ„œλ„ 각각의 μŠ€νƒ€μΌμ„ μ œλŒ€λ‘œ κ΅¬ν˜„ν•  수 μžˆλŠ” orderPizza() λ©”μ†Œλ“œλ₯Ό 가지고 μžˆλŠ” PizzaStore μ„œλΈŒν΄λž˜μŠ€λ“€μ„ ꡬ비할 수 μžˆμŠ΅λ‹ˆλ‹€.

뉴μ˜₯ 뢄점

public class NYPizzaStore extends PizzaStore {

    // μΆ”μƒλ©”μ†Œλ“œλ‘œ μ„ μ–Έλ˜μ—ˆκΈ° λ•Œλ¬Έμ— λ°˜λ“œμ‹œ κ΅¬ν˜„
    public Pizza createPizza(String item) {
        if(item.equals("cheese")){
            return new NYStyleCheesePize();
        }else if(item.equals("pepperoni")){
            return new NYStylePepperoniPizza();
        }else if(item.equals("clam")){
            return new NYStyleClamPizza();
        }else if(item.equals("veggie")){
            return new NYStyleVeggiePizza();
        }else{
            return null;
        }
    }
}

μˆ˜νΌν΄λž˜μŠ€μ— μžˆλŠ” orderPizza() λ©”μ†Œλ“œμ—μ„œλŠ” μ–΄λ–€ ν”Όμžκ°€ λ§Œλ“€μ–΄μ§€λŠ”μ§€ μ „ν˜€ μ•Œ 수 μ—†λ‹€λŠ” 점을 잘 μ΄ν•΄ν•΄μ•Όν•©λ‹ˆλ‹€. κ·Έ λ©”μ†Œλ“œμ—μ„œλŠ” ν”Όμžλ₯Ό μ€€λΉ„ν•˜κ³  κ΅½κ³  자λ₯΄κ³  포μž₯ν•˜λŠ” μž‘μ—…μ„ μ²˜λ¦¬ν•  λΏμž…λ‹ˆλ‹€.


# νŒ©ν† λ¦¬ λ©”μ†Œλ“œ μ„ μ–Έ

PizzaStoreλ₯Ό λͺ‡ ꡰ데 고친 κ²°κ³Ό,

ꡬ상 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 일을 ν•œ κ°μ²΄μ—μ„œ μ „λΆ€ μ²˜λ¦¬ν•˜λŠ” 방식 μ—μ„œ

일련의 μ„œλΈŒν΄λž˜μŠ€μ—μ„œ μ²˜λ¦¬ν•˜λŠ” 방식 으둜 λ„˜μ–΄μ˜€κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. ν•œλ²ˆ μžμ„Ένžˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public abstract class PizzaStore {

    public Pizza orederPizza(String type){
        Pizza pizza;

        pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }

    // Pizza μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 일을 이제 νŒ©ν† λ¦¬ 역할을 ν•˜λŠ” λ©”μ†Œλ“œμ—μ„œ λ§‘μ•„μ„œ 처리
    protected abstract Pizza createPizza(String type); 
}

νŒ©ν† λ¦¬ λ©”μ†Œλ“œλŠ” 객체 생성을 μ²˜λ¦¬ν•˜λ©°, νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•˜λ©΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” μž‘μ—…μ„ μ„œλΈŒν΄λž˜μŠ€μ—μ„œ μΊ‘μŠν™”μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μˆ˜νΌν΄λž˜μŠ€μ— μžˆλŠ” ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ™€ μ„œλΈŒν΄λž˜μŠ€μ— μžˆλŠ” 객체 생성 μ½”λ“œλ₯Ό λΆ„λ¦¬μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

abstract Product factoryMethod(String type)

# ν”Όμž μ£Όλ¬Έ

@에단 : λ‚˜λŠ” 뉴μ˜₯풍 ν”Όμžκ°€ μ’‹μ•„. μ–‡κ³  λ°”μ‚­λ°”μ‚­ν•œ 빡에 μΉ˜μ¦ˆλŠ” μ•½κ°„λ§Œ 올리고, λ§›μžˆλŠ” μ†ŒμŠ€λ₯Ό 써야 μ§„μ§œ ν”Όμž 맛이 λ‚˜μ§€.

ν”Όμž νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•œ ν”Όμž μ£Όλ¬Έ 과정을 ν•œλ²ˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

  1. 에단이 μ£Όλ¬Έν•œ 내역을 따라가 λ΄…μ‹œλ‹€. μš°μ„  NYPizzaStoreκ°€ ν•„μš”ν•©λ‹ˆλ‹€.

    PizzaStore nyPizzaStore = new NYPizzaStore();
    
  2. ν”Όμž κ°€κ²Œκ°€ ν™•λ³΄λμœΌλ‹ˆκΉŒ 주문을 받을 수 μžˆμŠ΅λ‹ˆλ‹€.

    nyPizzaStore.orderPizza("cheese");
    
  3. orderPizza() λ©”μ†Œλ“œμ—μ„œ createPizza() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

    Pizza pizza = createPizza("cheese");
    
  4. 아직 μ€€λΉ„κ°€ λ˜μ§€ μ•Šμ€ ν”Όμžλ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€. 이제 ν”Όμž λ§Œλ“œλŠ” μž‘μ—…μ„ λ§ˆλ¬΄λ¦¬ν•΄μ•Ό 되겠죠.

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();
    

mainμ—μ„œλŠ” μ–΄λ–»κ²Œ μž‘μ„±ν•΄μ•Όν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class PizzaTestDrive{

    public static void main(String[] args){
        PizzaStore nyStore = new NYPizzaStore();
        
        Pizza pizza = nyStore.orederPizza("cheese");
    }
}

# νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄

λͺ¨λ“  νŒ©ν† λ¦¬ νŒ¨ν„΄μ—μ„œλŠ” 객체 생성을 μΊ‘μŠν™”ν•©λ‹ˆλ‹€. νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄(Factory Method Pattern)μ—μ„œλŠ” μ„œλΈŒν΄λž˜μŠ€μ—μ„œ μ–΄λ–€ 클래슀λ₯Ό λ§Œλ“€μ§€λ₯Ό κ²°μ •ν•˜κ²Œ ν•¨μœΌλ‘œμ¨ 객체 생성을 μΊ‘μŠν™”ν•©λ‹ˆλ‹€. 클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ„ μ‚΄νŽ΄λ³΄λ©΄μ„œ 이 νŒ¨ν„΄μ— λ“±μž₯ν•˜λŠ” ν΄λž˜μŠ€λ“€μ„ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

# νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄ μ •μ˜

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ—μ„œλŠ” 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ”λ°, μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ§€λŠ” μ„œλΈŒμŠ€ν΄λž˜μŠ€μ—μ„œ κ²°μ •ν•˜κ²Œ λ§Œλ“­λ‹ˆλ‹€. νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ΄μš©ν•˜λ©΄ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 일을 μ„œλΈŒν΄λž˜μŠ€μ—κ²Œ λ§‘κΈ°λŠ” κ²ƒμž…λ‹ˆλ‹€.

클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ„ 보면, Creator 좔상 ν΄λž˜μŠ€μ—μ„œ 객체λ₯Ό λ§Œλ“€κΈ° μœ„ν•œ λ©”μ†Œλ“œ, 즉 νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•œλ‹€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. Creator 좔상 ν΄λž˜μŠ€μ— κ΅¬ν˜„λ˜μ–΄ μžˆλŠ” λ‹€λ₯Έ λ©”μ†Œλ“œμ—μ„œλŠ” νŒ©ν† λ¦¬ λ©”μ†Œλ“œμ— μ˜ν•΄ μƒμ‚°λœ μ œν’ˆμ„ 가지고 ν•„μš”ν•œ μž‘μ—…μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ‹€μ œ νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³  μ œν’ˆ(객체 μΈμŠ€ν„΄μŠ€)을 λ§Œλ“€μ–΄λ‚΄λŠ” 일은 μ„œλΈŒν΄λž˜μŠ€μ—μ„œλ§Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μœ„μ— μžˆλŠ” μ •μ˜μ—λ„ λ‚˜μ™€ μžˆμ§€λ§Œ, "κ²°μ •ν•œλ‹€" λΌλŠ” ν‘œν˜„μ„ μ“°λŠ” μ΄μœ λŠ” 이 νŒ¨ν„΄μ„ μ‚¬μš©ν•  λ•Œ μ„œλΈŒν΄λž˜μŠ€μ—μ„œ 싀행쀑에 μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ§€λ₯Ό κ²°μ •ν•˜κΈ° λ•Œλ¬Έμ΄ μ•„λ‹ˆλΌ, μƒμ‚°μž(Creator) 클래슀 μžμ²΄κ°€ μ‹€μ œ 생산될 μ œν’ˆμ— λŒ€ν•œ 사전 지식이 μ „ν˜€ 없이 λ§Œλ“€μ–΄μ§€κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 사싀 더 μ •ν™•ν•˜κ²Œ ν‘œν˜„ν•˜μžλ©΄, μ‚¬μš©ν•˜λŠ” μ„œλΈŒν΄λž˜μŠ€μ— 따라 μƒμ‚°λ˜λŠ” 객체 μΈμŠ€ν„΄μŠ€κ°€ 결정될 κ²ƒμž…λ‹ˆλ‹€.

# 바보같은 μ§ˆλ¬Έμ€ μ—†μŠ΅λ‹ˆλ‹€.

# λ§€κ°œλ³€μˆ˜ νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ ν˜•μ‹ μ•ˆμ •μ„±(type-safety)에 지μž₯이 μžˆμ§€ μ•Šλ‚˜μš”? κ·Έλƒ₯ String을 λ§€κ°œλ³€μˆ˜λ‘œ 전달할 λΏμ΄μž–μ•„μš”. "clam"을 잘λͺ» μ³μ„œ "calm"이라고 치면 μ–΄λ–»κ²Œ λ˜λŠ” κ±°μ£ ?

λ§Œμ•½ 그런 μ‹€μˆ˜λ₯Ό ν•˜κ²Œ 되면 μ†Œμœ„ "λŸ°νƒ€μž„ 였λ₯˜" λΌλŠ” 게 λ°œμƒν•˜κ²Œ λ©λ‹ˆλ‹€. λ§€κ°œλ³€μˆ˜ νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  λ•Œ ν˜•μ‹ μ•ˆμ •μ„±μ„ 쑰금 더 잘 보μž₯해쀄 수 μžˆλŠ” 기법듀이 있긴 ν•©λ‹ˆλ‹€. 그런 기법을 μ‚¬μš©ν•˜λ©΄ μ—‰λš±ν•œ ν˜•μ‹μ„ λ§Œλ“€μ–΄λ‚Ό 수 μžˆλŠ” 였λ₯˜λ₯Ό μ»΄νŒŒμΌμ‹œμ— μž‘μ•„λ‚Ό 수 있죠. 예λ₯Ό λ“€μ–΄ λ§€κ°œλ³€μˆ˜ ν˜•μ‹μ„ λ‚˜νƒ€λ‚΄κΈ° μœ„ν•œ 객체λ₯Ό λ§Œλ“€ μˆ˜λ„ 있고, 정적 μƒμˆ˜λ₯Ό μ“Έ μˆ˜λ„ 있고, μžλ°” 5λΆ€ν„°λŠ” enum을 μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

# κ°„λ‹¨ν•œ νŒ©ν† λ¦¬(Simple Factory)와 νŒ©ν† λ¦¬ λ©”μ†Œλ“œμ˜ 차이점을 아직 잘 λͺ¨λ₯΄κ² μ–΄μš”. νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ—μ„œλŠ” ν”Όμžλ₯Ό λ¦¬ν„΄ν•˜λŠ” ν΄λž˜μŠ€κ°€ μ„œλΈŒν΄λž˜μŠ€λΌλŠ” 점을 μ œμ™Έν•˜λ©΄ 거의 λ˜‘κ°™μž–μ•„μš”. 쑰금 더 μžμ„Ένžˆ μ„€λͺ…ν•΄ μ£Όμ‹€ 수 μžˆλ‚˜μš”?

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ΄ κ°„λ‹¨ν•œ νŒ©ν† λ¦¬μ™€ μƒλ‹Ήνžˆ λΉ„μŠ·ν•˜λ‹€λŠ” 지적은 λ§žμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ°„λ‹¨ν•œ νŒ©ν† λ¦¬λŠ” 일회용 μ²˜λ°©μ— λΆˆκ³Όν•œ 반면, νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ΄μš©ν•˜λ©΄ μ–΄λ–€ κ΅¬ν˜„μ„ 할지λ₯Ό μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ²°μ •ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬λ₯Ό λ§Œλ“€ 수 μžˆλ‹€λŠ” 결정적인 차이점이 μžˆμ§€μš”. 예λ₯Ό λ“€μ–΄, νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ—μ„œ μ‚¬μš©ν•œ orderPizza() λ©”μ†Œλ“œμ—μ„œλŠ” ν”Όμžλ₯Ό λ§Œλ“€κΈ° μœ„ν•œ 일반적인 ν”„λ ˆμž„μ›Œν¬λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. κ·Έ ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ ν”Όμžλ₯Ό λ§Œλ“œλŠ” ꡬ상 클래슀λ₯Ό λ§Œλ“€μ—ˆμ£ . PizzaStore 클래슀의 μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€ λ•Œ, μ–΄λ–€ ꡬ상 μ œν’ˆ ν΄λž˜μŠ€μ—μ„œ orderPizza()μ—μ„œ 리턴할 ν”Όμžλ₯Ό λ§Œλ“€μ§€λ₯Ό κ²°μ •ν•˜κ²Œ λ©λ‹ˆλ‹€. 이 ν”„λ ˆμž„μ›Œν¬λ₯Ό κ°„λ‹¨ν•œ νŒ©ν† λ¦¬ν•˜κ³  ν•œλ²ˆ 비ꡐ해 λ³΄μ„Έμš”. κ°„λ‹¨ν•œ νŒ©ν† λ¦¬μ—μ„œλŠ” 객체 생성을 μΊ‘μŠν™”ν•˜λŠ” 방법을 μ‚¬μš©ν•˜κΈ΄ ν•˜μ§€λ§Œ νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ²˜λŸΌ κ°•λ ₯ν•œ μœ μ—°μ„±μ„ μ œκ³΅ν•˜μ§„ λͺ»ν•©λ‹ˆλ‹€. μƒμ„±ν•˜λŠ” μ œν’ˆμ„ λ§ˆμŒλŒ€λ‘œ λ³€κ²½ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄μ£ .


# μ˜μ‘΄μ„± 뒀집기 원칙(Dependency Inversion Principle)

ꡬ상 ν΄λž˜μŠ€μ— λŒ€ν•œ μ˜μ‘΄μ„±μ„ μ€„μ΄λŠ” 것이 μ’‹λ‹€λŠ” 것은 이제 ν™•μ‹€νžˆ 이해할 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. 이런 λ‚΄μš©μ„ 정리해 놓은 객체지ν–₯ λ””μžμΈ 원칙이 λ°”λ‘œ μ˜μ‘΄μ„± 뒀집기 원칙(Dependecny Inversion Principle) μž…λ‹ˆλ‹€. 이 원칙은 λ‹€μŒκ³Ό 같은 μ‹μœΌλ‘œ μΌλ°˜ν™”μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

λ””μžμΈ 원칙 - μΆ”μƒν™”λœ 것에 μ˜μ‘΄ν•˜λ„λ‘ λ§Œλ“€μ–΄λΌ. ꡬ상 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜λ„λ‘ λ§Œλ“€μ§€ μ•Šλ„λ‘ ν•œλ‹€.

이 μ›μΉ™μ—μ„œλŠ” κ³ μˆ˜μ€€ κ΅¬μ„±μš”μ†Œκ°€ μ €μˆ˜μ€€ κ΅¬μ„±μš”μ†Œμ— μ˜μ‘΄ν•˜λ©΄ μ•ˆ λœλ‹€λŠ” 것이 λ‚΄ν¬λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 항상 좔상화에 μ˜μ‘΄ν•˜λ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. 그런데 λ„λŒ€μ²΄ 이게 무슨 μ†Œλ¦¬μΌκΉŒμš”? PizzaStoreλŠ” "κ³ μˆ˜μ€€ κ΅¬μ„±μš”μ†Œ"라고 ν•  수 있고, ν”Όμž ν΄λž˜μŠ€λ“€μ€ "μ €μˆ˜μ€€ κ΅¬μ„±μš”μ†Œ"라고 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. PizzaStore ν΄λž˜μŠ€λŠ” ꡬ상 ν”Όμž ν΄λž˜μŠ€λ“€μ— μ˜μ‘΄ν•˜κ³  μžˆλ‹€λŠ” 것을 ν™•μ‹€ν•˜κ²Œ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ˜μ‘΄μ„± 뒀집기 원칙에 μ˜ν•˜λ©΄, ꡬ상 클래슀처럼 ꡬ체적인 것이 μ•„λ‹Œ 좔상 ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€μ™€ 같이 좔상적인 것에 μ˜μ‘΄ν•˜λŠ” μ½”λ“œλ₯Ό λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. 이 μ›Œλ‹‰μ€ κ³ μˆ˜μ€€ λͺ¨λ“ˆκ³Ό μ €μˆ˜μ€€ λͺ¨λ“ˆμ— λͺ¨λ‘ 적용될 수 μžˆμŠ΅λ‹ˆλ‹€.

# μΆ”κ°€ μ„€λͺ…

κ³ μˆ˜μ€€ κ΅¬μ„±μš”μ†ŒλŠ” λ‹€λ₯Έ μ €μˆ˜μ€€ κ΅¬μ„±μš”μ†Œμ— μ˜ν•΄ μ •μ˜λ˜λŠ” 행동이 λ“€μ–΄μžˆλŠ” κ΅¬μ„±μš”μ†Œλ₯Ό λœ»ν•©λ‹ˆλ‹€.

에λ₯Ό λ“€μ–΄, PizzaStore의 행동은 ν”Όμžμ— μ˜ν•΄ μ •μ˜λ˜κΈ° λ•Œλ¬Έμ—, PizzaStoreλŠ” κ³ μˆ˜μ€€ κ΅¬μ„±μš”μ†ŒλΌκ³  ν•  수 μžˆμŠ΅λ‹ˆλ‹€. PizzaStoreμ—μ„œλŠ” λ‹€μ–‘ν•œ ν”Όμž 객체λ₯Ό λ§Œλ“€κ³ , ν”Όμžλ₯Ό μ€€λΉ„ν•˜κ³ , κ΅½κ³ , 자λ₯΄κ³ , 포μž₯ν•˜μ£ . μ΄λ•Œ PizzaStoreμ—μ„œ μ‚¬μš©ν•˜λŠ” ν”Όμž 객체듀은 μ €μˆ˜μ€€ κ΅¬μ„±μš”μ†ŒλΌκ³  ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

# μ‹¬ν•˜κ²Œ 의쑴적인 PizzaStore

μ‹¬ν•˜κ²Œ 의쑴적인 PizzaStore의 κ°€μž₯ 큰 λ¬Έμ œμ μ€ λͺ¨λ“  μ’…λ₯˜μ˜ ν”Όμžμ— μ˜μ‘΄ν•œλ‹€λŠ” μ μž…λ‹ˆλ‹€. orderPizza() λ©”μ†Œλ“œμ—μ„œ ꡬ상 ν˜•μ‹μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό 직접 λ§Œλ“€κΈ° λ•Œλ¬Έμ΄μ£ . λ°°μš΄λŒ€λ‘œ νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ μš©ν•˜κ³  λ‚˜λ©΄ λ‹€μ΄μ–΄κ·Έλž¨μ΄ λ‹€μŒκ³Ό 같이 λ°”λ€Œκ²Œ λ©λ‹ˆλ‹€.

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ μš©ν•˜κ³  λ‚˜λ©΄ κ³ μˆ˜μ€€ κ΅¬μ„±μš”μ†ŒμΈ PizzaStore의 μ €μˆ˜μ€€ κ΅¬μ„±μš”μ†ŒμΈ ν”Όμž 객체듀이 λͺ¨λ‘ 좔상 클래슀인 Pizza에 μ˜μ‘΄ν•˜κ²Œ λœλ‹€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ΄ μ˜μ‘΄μ„± 뒀집기 원칙을 μ€€μˆ˜ν•˜κΈ° μœ„ν•΄ μ“Έ 수 μžˆλŠ” μœ μΌν•œ 기법은 μ•„λ‹™λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ°€μž₯ μ ν•©ν•œ 방법 κ°€μš΄λ° ν•˜λ‚˜λΌκ³ λŠ” ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

# κ°€μ΄λ“œ 라인

λ‹€μŒκ³Ό 같은 κ°€μ΄λ“œ 라인을 λ”°λ₯΄λ©΄ μ˜μ‘΄μ„± 뒀집기 원칙에 μœ„λ°°λ˜λŠ” 객체지ν–₯ λ””μžμΈμ„ ν”Όν•˜λŠ” 데 도움이 λ©λ‹ˆλ‹€.

# μ–΄λ–€ λ³€μˆ˜μ—λ„ ꡬ상 ν΄λž˜μŠ€μ— λŒ€ν•œ 레퍼런슀λ₯Ό μ €μž₯ν•˜μ§€ λ§™μ‹œλ‹€.

new μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄ ꡬ상 ν΄λž˜μŠ€μ— λŒ€ν•œ 레퍼런슀λ₯Ό μ‚¬μš©ν•˜κ²Œ λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€. νŒ©ν† λ¦¬λ₯Ό μ¨μ„œ ꡬ상 ν΄λž˜μŠ€μ— λŒ€ν•œ 레퍼런슀λ₯Ό λ³€μˆ˜μ— μ €μž₯ν•˜λŠ” 일을 미리 λ°©μ§€ν•©μ‹œλ‹€.

# ꡬ상 ν΄λž˜μŠ€μ—μ„œ μœ λ„λœ 클래슀λ₯Ό λ§Œλ“€μ§€ λ§™μ‹œλ‹€.

ꡬ상 ν΄λž˜μŠ€μ—μ„œ μœ λ„λœ 클래슀λ₯Ό λ§Œλ“€λ©΄ νŠΉμ • ꡬ상 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜κ²Œ λ©λ‹ˆλ‹€. μΈν„°νŽ˜μ΄μŠ€λ‚˜ 좔상 클래슀처럼 μΆ”μƒν™”λœ κ²ƒμœΌλ‘œλΆ€ν„° 클래슀λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

# 베이슀 ν΄λž˜μŠ€μ— 이미 κ΅¬ν˜„λ˜μ–΄ 있던 λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œν•˜μ§€ λ§™μ‹œλ‹€.

이미 κ΅¬ν˜„λ˜μ–΄ μžˆλŠ” λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œν•œλ‹€λŠ” 것은 μ• μ΄ˆλΆ€ν„° 베이슀 ν΄λž˜μŠ€κ°€ μ œλŒ€λ‘œ μΆ”μƒν™”λœ 것이 μ•„λ‹ˆμ—ˆλ‹€κ³  λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 베이슀 ν΄λž˜μŠ€μ—μ„œ λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•  λ•ŒλŠ” λͺ¨λ“  μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ³΅μœ ν•  수 μžˆλ‹€λŠ” κ²ƒλ§Œ μ •μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.


# Conclusion

Factory Pattern은 맀우 μ€‘μš”ν•˜κ³  ν™œμš©λ„κ°€ 높은 νŒ¨ν„΄μ•„λ©° 그만큼 λ‚΄μš©λ„ λ°©λŒ€ν•©λ‹ˆλ‹€. λ‹€μŒ μž₯μ—μ„œλŠ” 상황을 μ’€ 더 μ„ΈλΆ„ν™”ν•˜μ—¬ λ¬Έμ œμ μ„ μ°Ύκ³  Abstract Factory Pattern으둜 κ·Έ 문제λ₯Ό 해결해보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.


# References

  • Head First Design Patterns
Last Updated: 8/12/2020, 1:33:42 PM