[λ””μžμΈνŒ¨ν„΄] μ „λž΅ νŒ¨ν„΄ , μŠ€νŠΈλž˜ν‹°μ§€ νŒ¨ν„΄ (Strategy Pattern)

λ°˜μ‘ν˜•

 

1. μ •μ˜

πŸ’‘ μ „λž΅ νŒ¨ν„΄ , μŠ€νŠΈλž˜ν‹°μ§€ νŒ¨ν„΄ (strategy pattern)
μ•Œκ³ λ¦¬μ¦˜κ΅°μ„ μ •μ˜ν•˜κ³  각각 μΊ‘μŠν™”ν•˜μ—¬ κ΅ν™˜ν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ§Œλ“ λ‹€. μŠ€νŠΈλž˜ν‹°μ§€ νŒ¨ν„΄μ„ ν™œμš©ν•˜λ©΄ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ™€λŠ” λ…λ¦½μ μœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ„ λ³€κ²½ν•  수 μžˆλ‹€.

'ν–‰μœ„(Behavioral) νŒ¨ν„΄'

ν–‰μœ„λ₯Ό 클래슀둜 μΊ‘μŠν™”ν•΄ λ™μ μœΌλ‘œ (μ „λž΅μ— 맞게) ν–‰μœ„λ₯Ό 자유둭게 λ°”κΏ€ 수 있게 ν•΄μ£ΌλŠ” νŒ¨ν„΄

 

μ „λž΅(Strategy)을 μ‰½κ²Œ λ°”κΏ€ 수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” νŒ¨ν„΄

μ—¬κΈ°μ„œ μ „λž΅μ΄λž€? μ–΄λ–€ λͺ©μ μ„ λ‹¬μ„±ν•˜κΈ° μœ„ν•΄ 일을 μˆ˜ν–‰ν•˜λŠ” 방식. λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™, λ¬Έμ œν•΄κ²° μ•Œκ³ λ¦¬μ¦˜ λ“±

 

2. [예제] μ˜€λ¦¬κ²Œμž„ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜

// 였리 슈퍼클래슀
public abstract class Duck {
    public Duck() {}

    public void quack() {
        System.out.println("κ½₯~~");
    }

    public void swim() {
        System.out.println("μˆ˜μ˜ν•œλ‹€~~");
    }

    public abstract void display(); // ꡬ체적인 μ˜€λ¦¬μ—μ„œ μž¬μ •μ˜
}
// Duck 을 ν™•μž₯ν•˜μ—¬ ReadHeadDuck μ •μ˜
public class RedHeadDuck extends Duck {
    @Override
    public void display() {
        System.out.println("RedHeadDuck.display() 좜λ ₯");
    }
}
// Duck 을 ν™•μž₯ν•˜μ—¬ MallardDuck μ •μ˜
public class MallardDuck extends Duck {
    @Override
    public void display() {
        System.out.println("MallardDuck.display() 좜λ ₯");
    }
}

(1) 문제 1 : 상속에 μ˜ν•œ 문제

μš”κ΅¬μ‚¬ν•­ : μ˜€λ¦¬κ°€ λ‚  수 있게 ν•΄μ£Όμ„Έμš”. 그리고 Rubber Duck 도 μΆ”κ°€ν•΄μ£Όμ„Έμš”. 근데 이 κ³ λ¬΄μ˜€λ¦¬λŠ” λ‚  수 μ—†μ–΄μš”.

// 였리 슈퍼클래슀
public abstract class Duck {
    public Duck() {}

    public void quack() {
        System.out.println("κ½₯~~");
    }

    public void swim() {
        System.out.println("μˆ˜μ˜ν•œλ‹€~~");
    }
    // λ‚  수 있게 κΈ°λŠ₯ μΆ”κ°€
    public void fly() {
        System.out.println("μ˜€λ¦¬λ‚ λ‹€~~");
    }
    
    public abstract void display(); // ꡬ체적인 μ˜€λ¦¬μ—μ„œ μž¬μ •μ˜
}
// Duck 을 ν™•μž₯ν•˜μ—¬ RubberDuck μ •μ˜ (λ‚  수 μ—†λŠ” 였리 μΆ”κ°€)
public class RubberDuck extends Duck {
    @Override
    public void display() {
        System.out.println("RubberDuck.display() 좜λ ₯");
    }

    @Override
    public void fly() {
        // μƒμ†λ•Œλ¬Έμ— 영ν–₯이 μžˆμ–΄ λ‚ μˆ˜ 없도둝 μž¬μ •μ˜ ν–ˆλ‹€.
        System.out.println("κ³ λ¬΄μ˜€λ¦¬λŠ” λͺ» λ‚ μ•„μš”");
    }
}
  • λ‚  수 μžˆλŠ” κΈ°λŠ₯을 μΆ”κ°€ν•΄μ£Όμ„Έμš”. : Duck μΆ”μƒν΄λž˜μŠ€μ— λ‚  수 μžˆλŠ” κΈ°λŠ₯ fly() λ₯Ό μΆ”κ°€ν•΄μ„œ ν•΄κ²°ν–ˆλ‹€.
  • Rubber Duck λ₯Ό μΆ”κ°€ν•΄μ£Όμ„Έμš”. : Duck 클래슀λ₯Ό ν™•μž₯ν•΄μ„œ RubberDuck λ₯Ό μ •μ˜ν–ˆλ‹€.
  • 근데, Rubber Duck은 λ‚  수 μ—†μ–΄μš”. : Duck 클래슀λ₯Ό 상속받고 μžˆμ–΄ λ‚ κ³ μžˆλ‹€. fly() λ₯Ό μž¬μ •μ˜ν•΄μ„œ λ‚  수 μ—†κ²Œ ν–ˆλ‹€.

 

λ¬Έμ œλŠ” μ–ΌμΆ” ν•΄κ²°λœ κ²ƒμœΌλ‘œ 보인닀.

그런데, μ•žμœΌλ‘œ Rubber Duck과같이 λ‚  수 μ—†λŠ” μ˜€λ¦¬κ°€ 또 μΆ”κ°€λœλ‹€λ©΄ κ·Έλ•Œλ§ˆλ‹€ λ©”μ†Œλ“œλ₯Ό ν•˜λ‚˜ν•˜λ‚˜ ν™•μΈν•˜λ©° μ˜€λ²„λΌμ΄λ“œ ν•΄μ„œ κ΅¬ν˜„ν•΄μ€˜μ•Όν•œλ‹€.

 

(2) 문제 2 : μΈν„°νŽ˜μ΄μŠ€μ— μ˜ν•œ 문제

νšŒμ‚¬μ—μ„œ 1κ°œμ›”λ§ˆλ‹€ μƒˆλ‘œμš΄ 였리λ₯Ό μ—…λ°μ΄νŠΈ ν•  μ˜ˆμ •μ΄λΌκ³  ν•œλ‹€. 또 각각의 νŠΉμ„±λ„ λ‹€μ–‘ν•  것이라고 ν•œλ‹€. κ½₯ ν•˜λŠ” μ†Œλ¦¬λ„ λ‹€ λ‹€λ₯΄κ³ , λ‚  수 μ—†λŠ” μ˜€λ¦¬λ„ μžˆμ„ 것이라고 ν•œλ‹€. ν˜„μž¬ μ‹œμŠ€ν…œμ€ μƒμ†μœΌλ‘œ 였리λ₯Ό μƒμ„±ν•˜κ³  μžˆκΈ°λ•Œλ¬Έμ— μ˜€λ¦¬κ°€ μΆ”κ°€ 될 λ•Œλ§ˆλ‹€ quack() λ©”μ†Œλ“œμ™€ fly() λ©”μ†Œλ“œλ₯Ό λ‹€ μ‚΄νŽ΄λ΄μ•Ό ν•œλ‹€.

이러면 μƒμ†ν™œμš©μ΄ νƒ€λ‹Ήν•˜μ§€ μ•Šλ‹€. κ·Έλ ‡λ‹€λ©΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•΄λ³΄λ©΄ μ–΄λ–¨κΉŒ?

// fly μΈν„°νŽ˜μ΄μŠ€
public interface Flyable {
    void fly();
}
// quack μΈν„°νŽ˜μ΄μŠ€
public interface Quackable {
    void quack();
}
// RubberDuck : Duck 을 상속받고, Flyable κ³Ό Quackable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„
public class RubberDuck extends Duck implements Flyable, Quackable {
    @Override
    public void display() {
        System.out.println("RubberDuck.display() 좜λ ₯");
    }
    // μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„
    public void fly() {
        System.out.println("κ³ λ¬΄μ˜€λ¦¬λŠ” λͺ» λ‚ μ•„μš”");
    }
    public void quack(){
        System.out.println("κΎΈμ•‘");
    }
}

μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ 각 μ„œλΈŒν΄λž˜μŠ€μ—μ„œ λͺ¨λ“  μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ£Όμ–΄μ•Ό ν•˜λ‹ˆ μ½”λ“œ 쀑볡이 μ—„μ²­λ‚˜κ²Œ λ°œμƒν•œλ‹€. λ©”μ†Œλ“œ λͺ‡κ°œ μ˜€λ²„λΌμ΄λ“œ ν•΄μ•Όν•˜λŠ” 것을 ν”Όν•˜λ €λ‹€κ°€ λͺ¨λ“  Duck 의 μ„œλΈŒν΄λž˜μŠ€λ₯Ό μ „λΆ€ 고쳐야 ν•˜κ²Œ λ˜λ²„λ¦°λ‹€.

 

3. λ‹€λ₯Έ 해결방법

μœ„μ—μ„œ ν™•μΈν•œ 문제점 2가지

  1. 상속을 μ‚¬μš©ν•˜λŠ” 방법은 μ„œλΈŒν΄λž˜μŠ€λ“€μ˜ 행동이 λ°”λ€” 수 μžˆλŠ”λ°λ„ λͺ¨λ“  μ„œλΈŒν΄λž˜μŠ€λ“€μ΄ ν•˜λ‚˜μ˜ 행동을 μ‚¬μš©ν•˜λŠ” 것이 λ¬Έμ œκ°€ λœλ‹€.
  2. Flyable, Quackable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 방법은 μ½”λ“œμž¬μ‚¬μš©μ„ ν•  수 μ—†λ‹€. 즉, ν•œκ°€μ§€μ˜ 행동을 λ°”κΏ€λ•Œλ§ˆλ‹€ κ·Έ 행동이 μ •μ˜λ˜μ–΄ μžˆλŠ” λͺ¨λ“  μ„œλΈŒν΄λž˜μŠ€λ“€μ„ μ „λΆ€ μ°Ύμ•„μ„œ μ½”λ“œλ₯Ό κ³ μ³μ€˜μ•Όν•˜κ³ , κ·Έ κ³Όμ •μ—μ„œ 예기치λͺ»ν•œ μƒˆλ‘œμš΄ 버그가 λ°œμƒν•  κ°€λŠ₯성이 맀우 λ†’λ‹€.
πŸ“Œ λ””μžμΈμ›μΉ™
μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ‹¬λΌμ§€λŠ” λΆ€λΆ„λ“€ μ°Ύμ•„λ‚΄κ³ , 달라지지 μ•ŠλŠ” λΆ€λΆ„μœΌλ‘œλΆ€ν„° λΆ„λ¦¬μ‹œν‚¨λ‹€.
λ‹¬λΌμ§€λŠ” 뢀뢄을 μ°Ύμ•„λ‚΄μ„œ λ‚˜λ¨Έμ§€ μ½”λ“œμ— 영ν–₯을 주지 μ•Šλ„λ‘ μΊ‘μŠν™” μ‹œμΌœμ€€λ‹€.

 

λ‹¬λΌμ§€λŠ” λΆ€λΆ„ : fly(), quack() -> Duck ν΄λž˜μŠ€λ‘œλΆ€ν„° λΆ„λ¦¬μ‹œν‚€κΈ°μœ„ν•΄ 각 행동을 λ‚˜νƒ€λ‚Ό 클래슀의 집합을 λ§Œλ“€μ–΄μ£Όμž.

// fly 행동 클래슀 집합
public interface FlyBehavior {
    void fly();
}
// quack 행동 클래슀 집합
public interface QuackBehavior {
    void quack();
}
// λ‚  수 μ—†λŠ” 행동 κ΅¬ν˜„ : FlyNoWay (행동을 μœ„μž„)
public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("λͺ» λ‚ μ•„μš”!");
    }
}
// λ‚  수 μžˆλŠ” 행동 κ΅¬ν˜„ : FlyWithWings (행동을 μœ„μž„)
public class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("λ‚ κ³  μžˆμ–΄μš”!");
    }
}
// κ½₯ κ΅¬ν˜„ : QuackBehavior (행동을 μœ„μž„)
public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("κ½₯");        
    }
}
// κ°€μ§œ κ½₯ κ΅¬ν˜„ : QuackBehavior (행동을 μœ„μž„)
public class FakeQuack implements QuackBehavior {
    public void quack() {
        System.out.println("κΎΈμ• μ•‘");        
    }
}

μ΄λ ‡κ²Œ 행동을 λΆ„λ¦¬μ‹œν‚¨λ‹€. 행동에 κ΄€ν•œ μΈν„°νŽ˜μ΄μŠ€κ°€ 생기고 ꡬ체적인 행동을 κ΅¬ν˜„ν•˜λŠ” ν΄λž˜μŠ€λ“€μ΄ 각각 μƒμ„±λœλ‹€.

이제 더이상 λ‚˜λŠ” 행동 fly() 와 μ†Œλ¦¬λ‚΄λŠ” 행동 quack() λ₯Ό Duck ν΄λž˜μŠ€λ‚˜ κ·Έ μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•˜μ§€ μ•Šκ³  λ‹€λ₯Έ ν΄λž˜μŠ€μ— μœ„μž„μ„ ν•΄μ£Όκ²Œ λœλ‹€.

πŸ“Œ λ””μžμΈμ›μΉ™
μƒμ†λ³΄λ‹€λŠ” ꡬ성을 ν™œμš©ν•œλ‹€.
πŸ“Œ λ””μžμΈμ›μΉ™
κ΅¬ν˜„μ΄ μ•„λ‹Œ μΈν„°νŽ˜μ΄μŠ€μ— λ§žμΆ°μ„œ ν”„λ‘œκ·Έλž˜λ°ν•œλ‹€.
// Duck ν΄λž˜μŠ€μ—μ„œ 이제 행동을 μ§μ ‘μ²˜λ¦¬ ν•˜μ§€μ•Šκ³  각 행동을 μ°Έμ‘°ν•˜κ³  μœ„μž„ν•΄μ€€λ‹€.
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {}

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public void performFly() {
        flyBehavior.fly();
    }
    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("μˆ˜μ˜ν•œλ‹€~~");
    }

    public abstract void display();
}

"A λŠ” B 이닀" 보닀 "A μ—λŠ” B κ°€ μžˆλ‹€" κ°€ λ‚˜μ„ 수 μžˆλ‹€.

각각의 μ˜€λ¦¬λ“€μ—κ²ŒλŠ” FlyBehavior 와 QuackBehavior 이 있으며 각각 λ‚˜λŠ” 행동과 μ†Œλ¦¬λ‚΄λŠ” 행동을 μœ„μž„λ°›λŠ”λ‹€.

μ΄λŸ°μ‹μœΌλ‘œ 두 클래슀λ₯Ό ν•©μΉ˜λŠ” 것을 ꡬ성 (composition) 을 μ΄μš©ν•˜λŠ” 것이라고 ν•œλ‹€.

μ—¬κΈ°μ˜ 였리 ν΄λž˜μŠ€λŠ” 행동을 μƒμ†λ°›λŠ” λŒ€μ‹  μ˜¬λ°”λ₯Έ 행동 객체둜 κ΅¬μ„±λ¨μœΌλ‘œμ¨ 행동을 λΆ€μ—¬λ°›κ²Œ λœλ‹€.

 

4. 예제2

1. Strategy μΈν„°νŽ˜μ΄μŠ€

public interface Strategy {
    void algorithmInterface();
}

2. Strategy μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ ( 각 μ „λž΅μ„ κ΅¬ν˜„ν•œλ‹€)

// μ „λž΅ A κ΅¬ν˜„
@Slf4j
public class StrategyLogicA implements Strategy {
    @Override
    public void algorithmInterface() {
        log.info("μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ A");
    }
}
// μ „λž΅ B κ΅¬ν˜„
@Slf4j
public class StrategyLogicB implements Strategy {
    @Override
    public void algorithmInterface() {
        log.info("μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ B");
    }
}

3. μ „λž΅μ„ μ‚¬μš©ν•˜λŠ” Context

@Slf4j
public class Context {

    public void execute(Strategy strategy) {
        Long startTime = System.currentTimeMillis();

        // λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ‹€ν–‰
        strategy.algorithmInterface(); // 각 μ „λž΅μ— μœ„μž„
        // λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ’…λ£Œ

        Long endTime = System.currentTimeMillis();
        Long resultTime = endTime - startTime;
        log.info("resultTime = {}", resultTime); // μ‹€ν–‰μ‹œκ°„ 좜λ ₯
    }
    
}

4. μ‹€ν–‰

/**
 * μ „λž΅ νŒ¨ν„΄ 적용
 */
@Test
void strategy1() {
    Context context = new Context();
    context.execute(new StrategyLogicA()); // Context의 둜직 μ‹€ν–‰μ‹œ νŒŒλΌλ―Έν„°λ‘œ μ „λž΅ 전달
    context.execute(new StrategyLogicB());
}
/**
 * μ „λž΅ νŒ¨ν„΄ 읡λͺ… λ‚΄λΆ€ 클래슀, λžŒλ‹€ μ‚¬μš©ν•˜λŠ” 경우
 */
@Test
void strategy2() {
    Context context = new Context();
    context.execute(new Strategy() { // 읡λͺ… λ‚΄λΆ€ 클래슀 κ°€λŠ₯
        @Override
        public void algorithmInterface() {
            log.info("μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ - A");
        }
    });
    context.execute(() -> log.info("μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„2")); // λžŒλ‹€ κ°€λŠ₯
}

5. 좜λ ₯κ²°κ³Ό 확인

// strategy1 κ²°κ³Ό (둜그의 νŒ¨ν‚€μ§€λͺ… μƒλž΅)
..μƒλž΅..StrategyLogicA - μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ A
..μƒλž΅..Context - resultTime = 11
..μƒλž΅..StrategyLogicB - μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ B
..μƒλž΅..Context - resultTime = 0
// strategy2 κ²°κ³Ό (둜그의 νŒ¨ν‚€μ§€λͺ… μƒλž΅)
..μƒλž΅..ContextTest - μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ - A
..μƒλž΅..Context - resultTime = 1
..μƒλž΅..ContextTest - μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„2
..μƒλž΅..Context - resultTime = 1

 

5. UML Class Diagram

 

6. GOF λ””μžμΈ νŒ¨ν„΄ μ •μ˜

μ•Œκ³ λ¦¬μ¦˜ μ œν’ˆκ΅°μ„ μ •μ˜ν•˜κ³  각각을 μΊ‘μŠν™”ν•˜μ—¬ μƒν˜Έ κ΅ν™˜ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€μž. μ „λž΅μ„ μ‚¬μš©ν•˜λ©΄ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ™€ λ…λ¦½μ μœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ„ λ³€κ²½ν•  수 μžˆλ‹€.

μ „λž΅ νŒ¨ν„΄μ€ λ³€ν•˜μ§€ μ•ŠλŠ” 뢀뢄을 Context (λ¬Έλ§₯) λΌλŠ” 곳에 두고, λ³€ν•˜λŠ” 뢀뢄을 Strategy λΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“€κ³  ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ ν•΄μ„œ 문제λ₯Ό ν•΄κ²°ν•œλ‹€. Context 의 λ‚΄λΆ€ ν•„λ“œμ— Strategy λ₯Ό μ£Όμž…ν•΄μ„œ μ‚¬μš©ν•œλ‹€. 상속이 μ•„λ‹ˆλΌ μœ„μž„μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•œλ‹€.

 

β–  Context 의 내뢀에 Strategy λ₯Ό 두고 μ‚¬μš©ν•˜λŠ” 방식

Context 와 Strategy λ₯Ό ν•œλ²ˆ μ‘°λ¦½ν•˜κ³  λ‚˜λ©΄ μ΄ν›„λ‘œλŠ” Context λ₯Ό μ‹€ν–‰ν•˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€. μŠ€ν”„λ§μœΌλ‘œ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•  λ•Œ λ‘œλ”©λ˜λŠ” μ‹œμ μ— ν•„μš”ν•œ μ˜μ‘΄κ΄€κ³„λ₯Ό μ£Όμž…ν•΄λ‘κ³  μ‹€μ œ μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” 것과 같은 원리이닀.

단점은 Context 와 Strategy λ₯Ό μ‘°λ¦½ν•œ μ΄ν›„μ—λŠ” μ „λž΅μ„ λ³€κ²½ν•˜κΈ°κ°€ λ²ˆκ±°λ‘­λ‹€λŠ” 점이닀. Context 에 setter λ₯Ό λ§Œλ“€μ–΄ Strategy λ₯Ό λ„˜κ²¨ λ³€κ²½ν•˜λ©΄ λ˜μ§€λ§Œ, Context λ₯Ό μ‹±κΈ€ν†€μœΌλ‘œ μ‚¬μš©ν•˜λ©΄ λ™μ‹œμ„± μ΄μŠˆλ“±μ˜ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

κ·Έλž˜μ„œ μ „λž΅μ„ μ‹€μ‹œκ°„μœΌλ‘œ λ³€κ²½ν•΄μ•Ό ν•˜λ©΄ 차라리 Context λ₯Ό ν•˜λ‚˜ 더 μƒμ„±ν•΄μ„œ λ‹€λ₯Έ Strategy λ₯Ό μ£Όμž…ν•˜λŠ” 것이 더 λ‚˜μ€ 선택이 될 수 μžˆλ‹€.


μ°Έκ³ 
ν—€λ“œ 퍼슀트 λ””μžμΈ νŒ¨ν„΄ (Head First Design Patterns) - 에릭 프리먼,μ—˜λ¦¬μžλ² μŠ€ 둭슨,μΌ€μ΄μ‹œ μ‹œμ—λΌ,λ²„νŠΈ 베이츠

λ°˜μ‘ν˜•