관리 메뉴

deVlog

[λ””μžμΈ νŒ¨ν„΄] ν–‰μœ„ νŒ¨ν„΄ - Template Method Pattern (ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄) λ³Έλ¬Έ

πŸ› οΈ Software Architecture/Design Pattern

[λ””μžμΈ νŒ¨ν„΄] ν–‰μœ„ νŒ¨ν„΄ - Template Method Pattern (ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄)

은루밍 2025. 2. 12. 15:42

λͺ©μ°¨

     

     

    πŸ“‡ κ°œμš”

    ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ€ μƒμœ„ 클래슀(좔상 클래슀)μ—μ„œ μ•Œκ³ λ¦¬μ¦˜μ˜ ꡬ쑰λ₯Ό μ •μ˜ν•˜κ³ , ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ„ΈλΆ€ κ΅¬ν˜„μ„ λ‹΄λ‹Ήν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€.

    즉, μ•Œκ³ λ¦¬μ¦˜μ˜ λΌˆλŒ€λŠ” ν…œν”Œλ¦Ώ λ©”μ„œλ“œκ°€ μ •μ˜ν•˜κ³ , ꡬ체적인 λ™μž‘μ€ ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ”©ν•˜μ—¬ κ΅¬ν˜„ν•˜λŠ” 방식이닀.

     

    νŠΉμ§•

    • μ•Œκ³ λ¦¬μ¦˜ ꡬ쑰λ₯Ό μž¬μ‚¬μš©ν•  수 μžˆλ‹€.
    • μΌκ΄€λœ μ‹€ν–‰ 흐름을 보μž₯ν•˜λ©΄μ„œλ„ μ„ΈλΆ€ κ΅¬ν˜„μ„ λ³€κ²½ν•  수 μžˆλ‹€.
    • μ½”λ“œ 쀑볡을 쀄이고 μœ μ§€λ³΄μˆ˜λ₯Ό μ‰½κ²Œ λ§Œλ“ λ‹€.

     

    πŸ‘©πŸ»‍πŸ’» μ½”λ“œλ‘œ μ•Œμ•„λ³΄μž

    컀피와 μ°¨λ₯Ό λ§Œλ“œλŠ” 과정을 ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μœΌλ‘œ κ΅¬ν˜„ν•΄λ³΄μž

    // 1. ν…œν”Œλ¦Ώ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” 좔상 클래슀
    abstract class Beverage {
        // ν…œν”Œλ¦Ώ λ©”μ„œλ“œ (μ΅œμ’… μ‹€ν–‰ 흐름을 μ •μ˜)
        public final void prepareRecipe() {
            boilWater();
            brew();
            pourInCup();
            if (customerWantsCondiments()) { // 후크(Hook) λ©”μ„œλ“œ μ‚¬μš©
                addCondiments();
            }
        }
    
        // 곡톡 κ΅¬ν˜„ (λͺ¨λ“  μŒλ£Œκ°€ κ³΅μœ ν•˜λŠ” 둜직)
        private void boilWater() {
            System.out.println("물을 λ“μ΄λŠ” 쀑...");
        }
    
        private void pourInCup() {
            System.out.println("컡에 λ”°λ₯΄λŠ” 쀑...");
        }
    
        // ν•˜μœ„ ν΄λž˜μŠ€κ°€ κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” 좔상 λ©”μ„œλ“œ
        abstract void brew();
        abstract void addCondiments();
    
        // 후크 λ©”μ„œλ“œ (μ„ νƒμ μœΌλ‘œ μ˜€λ²„λΌμ΄λ”© κ°€λŠ₯)
        boolean customerWantsCondiments() {
            return true;
        }
    }
    
    // 2. ν•˜μœ„ 클래슀 - 컀피 λ§Œλ“€κΈ°
    class Coffee extends Beverage {
        @Override
        void brew() {
            System.out.println("컀피λ₯Ό λ‚΄λ¦¬λŠ” 쀑...");
        }
    
        @Override
        void addCondiments() {
            System.out.println("섀탕과 우유λ₯Ό μΆ”κ°€ν•˜λŠ” 쀑...");
        }
    }
    
    // 3. ν•˜μœ„ 클래슀 - μ°¨ λ§Œλ“€κΈ°
    class Tea extends Beverage {
        @Override
        void brew() {
            System.out.println("μ°¨λ₯Ό μš°λ €λ‚΄λŠ” 쀑...");
        }
    
        @Override
        void addCondiments() {
            System.out.println("레λͺ¬μ„ μΆ”κ°€ν•˜λŠ” 쀑...");
        }
    }
    
    // μ‹€ν–‰ μ½”λ“œ
    public class TemplateMethodExample {
        public static void main(String[] args) {
            System.out.println("β˜• 컀피 μ€€λΉ„");
            Beverage coffee = new Coffee();
            coffee.prepareRecipe();
    
            System.out.println("\n🍡 μ°¨ μ€€λΉ„");
            Beverage tea = new Tea();
            tea.prepareRecipe();
        }
    }
    • prepareRecipe() λ©”μ„œλ“œκ°€ μ•Œκ³ λ¦¬μ¦˜μ˜ ꡬ쑰λ₯Ό μ •μ˜ν•˜λŠ” ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ΄λ‹€.
    • brew() μ™€ addCondiments() λŠ” ν•˜μœ„ ν΄λž˜μŠ€κ°€ κ΅¬ν˜„ν•˜λŠ” μΆ”상 λ©”μ„œλ“œμ΄λ‹€.
    • customerWantsCondiments() ν›„크(Hook) λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄, ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ„ νƒμ μœΌλ‘œ κΈ°λŠ₯을 λ³€κ²½ν•  수 μžˆλ‹€.
    • 덕뢄에 μƒˆλ‘œμš΄ μŒλ£Œκ°€ 좔가될 λ•Œ μ½”λ“œ μˆ˜μ • 없이 ν™•μž₯ν•  수 μžˆλ‹€.

     

     

     

    ☘️ μž₯/단점

    βœ… μž₯점

    1. μ½”λ“œ 쀑볡 κ°μ†Œ

    • μ•Œκ³ λ¦¬μ¦˜μ˜ 곡톡적인 흐름을 μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ •μ˜ν•˜κ³ , μ„ΈλΆ€ κ΅¬ν˜„λ§Œ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ λ‹€λ₯΄κ²Œ μž‘μ„±ν•˜λ©΄ λ˜λ―€λ‘œ μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•  수 μžˆλ‹€.
    • λ™μΌν•œ λ‘œμ§μ„ μ—¬λŸ¬ κ³³μ—μ„œ 쀑볡 κ΅¬ν˜„ν•  ν•„μš”κ°€ μ—†λ‹€.

    2. μΌκ΄€λœ μ•Œκ³ λ¦¬μ¦˜ ꡬ쑰 μœ μ§€

    • μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³  μœ μ§€ν•  수 μžˆλ‹€.
    • νŠΉμ • λ‹¨κ³„μ˜ λ™μž‘λ§Œ λ³€κ²½ν•˜κ³  싢을 λ•Œ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ ν•„μš”ν•œ λΆ€λΆ„λ§Œ μ˜€λ²„λΌμ΄λ”©ν•˜λ©΄ λœλ‹€.

    3. ν™•μž₯성이 뛰어남 (OCP 원칙 μ€€μˆ˜)

    • μƒˆλ‘œμš΄ κΈ°λŠ₯이 ν•„μš”ν•  경우, κΈ°μ‘΄ μ½”λ“œλ₯Ό μˆ˜μ •ν•˜μ§€ μ•Šκ³  μƒˆλ‘œμš΄ ν•˜μœ„ 클래슀λ₯Ό μΆ”κ°€ν•˜λŠ” λ°©μ‹μœΌλ‘œ ν™•μž₯ν•  수 μžˆλ‹€.
    • μ΄λŠ” 개방-폐쇄 원칙(Open-Closed Principle, OCP)을 λ”°λ₯΄λŠ” 섀계 방식이닀.

    4. ν›„크(Hook) λ©”μ„œλ“œλ₯Ό ν™œμš©ν•œ μœ μ—°ν•œ κ΅¬ν˜„ κ°€λŠ₯

    • 후크(Hook) λ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜λ©΄ ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ„ νƒμ μœΌλ‘œ λ™μž‘μ„ λ³€κ²½ν•  수 μžˆλ‹€.
    • 예λ₯Ό λ“€μ–΄, customerWantsCondiments() 같은 후크 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 쑰건에 따라 κΈ°λŠ₯을 ν™œμ„±ν™”ν•  수 μžˆλ‹€.

     

    ❌ λ‹¨μ 

    1. ν•˜μœ„ ν΄λž˜μŠ€κ°€ λ§Žμ•„μ§ˆ 경우 λ³΅μž‘ν•΄μ§ˆ 수 있음

    • ν…œν”Œλ¦Ώ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν• μˆ˜λ‘ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ„ΈλΆ€ κ΅¬ν˜„μ„ λ‹΄λ‹Ήν•΄μ•Ό ν•˜λ―€λ‘œ, λ„ˆλ¬΄ λ§Žμ€ ν•˜μœ„ ν΄λž˜μŠ€κ°€ 생길 수 μžˆλ‹€.
    • μ΄λŠ” μ½”λ“œμ˜ λ³΅μž‘μ„±μ„ μ¦κ°€μ‹œν‚€κ³  μœ μ§€λ³΄μˆ˜λ₯Ό μ–΄λ ΅κ²Œ λ§Œλ“€ 수 μžˆλ‹€.

    2. μ„€κ³„κ°€ 잘λͺ»λ˜λ©΄ μœ μ—°μ„±μ΄ λ–¨μ–΄μ§ˆ 수 있음

    • μ•Œκ³ λ¦¬μ¦˜μ˜ 흐름이 μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ •ν•΄μ Έ 있기 λ•Œλ¬Έμ—, νŠΉμ • λ‹¨κ³„μ—μ„œ λ³€ν™”λ₯Ό μ£Όκ³  싢어도 ꡬ쑰적으둜 μ–΄λ ΅κ±°λ‚˜ μ œν•œμ΄ μžˆμ„ 수 μžˆλ‹€.
    • λͺ¨λ“  경우λ₯Ό λ‹€ λ°˜μ˜ν•˜λ €κ³  ν•˜λ©΄ ν…œν”Œλ¦Ώ λ©”μ„œλ“œ μžμ²΄κ°€ λ„ˆλ¬΄ λ³΅μž‘ν•΄μ§ˆ 수 μžˆλ‹€.

    3. λ‹¨μΌ μ±…μž„ 원칙(SRP) μœ„λ°˜ κ°€λŠ₯μ„±

    • μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ•Œκ³ λ¦¬μ¦˜μ˜ 전체적인 흐름을 μ •μ˜ν•˜λ©΄μ„œ λ„ˆλ¬΄ λ§Žμ€ μ±…μž„μ„ κ°€μ§€κ²Œ 될 κ°€λŠ₯성이 μžˆλ‹€.
    • μ΄λŠ” μœ μ§€λ³΄μˆ˜μ„±κ³Ό 가독성을 μ €ν•˜μ‹œν‚¬ 수 μžˆλ‹€.

    4. λ””버깅이 μ–΄λ €μšΈ 수 있음

    • ν…œν”Œλ¦Ώ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λ©”μ„œλ“œ 호좜이 μƒμœ„ ν΄λž˜μŠ€μ™€ ν•˜μœ„ 클래슀 μ‚¬μ΄μ—μ„œ μ΄λ£¨μ–΄μ§€λ―€λ‘œ, λ””버깅이 μ–΄λ €μšΈ 수 μžˆλ‹€.
    • 특히, 후크 λ©”μ„œλ“œκ°€ μ˜ˆμƒμΉ˜ λͺ»ν•œ λ™μž‘μ„ ν•˜κ±°λ‚˜, ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ˜€λ²„λΌμ΄λ”©μ΄ 잘λͺ»λ  경우 원인을 μ°ΎκΈ° μ–΄λ ΅λ‹€.

     

    πŸ“Œ μ •리

    ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ€ μ•Œκ³ λ¦¬μ¦˜μ˜ 곡톡 뢀뢄을 μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ •μ˜ν•˜κ³ , μ„ΈλΆ€ 사항은 ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•˜λ„λ‘ κ°•μ œν•˜λŠ” νŒ¨ν„΄μ΄λ‹€.

     

    μ•Œκ³ λ¦¬μ¦˜μ˜ ꡬ쑰λ₯Ό μž¬μ‚¬μš©ν•˜λ©΄μ„œλ„ μœ μ—°ν•œ ν™•μž₯을 κ°€λŠ₯ν•˜κ²Œ ν•΄μ£ΌλŠ” κ°•λ ₯ν•œ νŒ¨ν„΄μ΄λΌλŠ” μž₯점을 κ°€μ§€μ§€λ§Œ,
    λ„ˆλ¬΄ λ§Žμ€ ν•˜μœ„ ν΄λž˜μŠ€κ°€ ν•„μš”ν•˜κ±°λ‚˜ μ§€λ‚˜μΉ˜κ²Œ λ³΅μž‘ν•œ ꡬ쑰λ₯Ό λ§Œλ“€ 경우 였히렀 μœ μ§€λ³΄μˆ˜κ°€ μ–΄λ €μ›Œμ§ˆ 수 μžˆλ‹€.
    λ”°λΌμ„œ, νŒ¨ν„΄μ„ μ μš©ν•  λ•ŒλŠ” μ μ ˆν•œ κ²½μš°μ—λ§Œ μ‚¬μš©ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

     

    βœ… μ–Έμ œ μ‚¬μš©ν•˜λ©΄ μ’‹μ„κΉŒ?

    • κ³΅ν†΅λœ μ•Œκ³ λ¦¬μ¦˜ 흐름이 있으며, μΌλΆ€λ§Œ λ‹€λ₯΄κ²Œ κ΅¬ν˜„ν•΄μ•Ό ν•  λ•Œ.
    • μ½”λ“œ 쀑볡을 쀄이고, ν™•μž₯성을 높이고 싢을 λ•Œ.
    • μ•Œκ³ λ¦¬μ¦˜μ˜ λ³€κ²½ 없이 μƒˆλ‘œμš΄ κΈ°λŠ₯을 μ‰½κ²Œ μΆ”κ°€ν•˜κ³  싢을 λ•Œ.

    ❌ μ–Έμ œ ν”Όν•΄μ•Ό ν• κΉŒ?

    • ν•˜μœ„ ν΄λž˜μŠ€κ°€ λ„ˆλ¬΄ λ§Žμ•„μ Έμ„œ λ³΅μž‘λ„κ°€ 증가할 λ•Œ.
    • μœ μ—°ν•œ ν™•μž₯이 ν•„μš”ν•œλ° ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ˜ μ œν•œμ΄ λ§Žμ„ λ•Œ.
    • μ•Œκ³ λ¦¬μ¦˜μ΄ λ„ˆλ¬΄ λ‹€μ–‘ν•΄μ„œ μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ •μ˜ν•˜κΈ° μ–΄λ €μšΈ λ•Œ.

     

     

    πŸ“‹ μ°Έκ³