[Spring] 예제둜 μ•Œμ•„λ³΄λŠ” [ μ „λž΅ νŒ¨ν„΄ ]

2022. 5. 31. 12:07ㆍBackend/🌿 Spring

이전 ν¬μŠ€νŒ…μ—μ„œ ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ„ μ•Œμ•„λ΄€κ³ , ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ μƒμ†μ΄λΌλŠ” ν•œκ³„λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ „λž΅ νŒ¨ν„΄μ„ ν™œμš©ν•˜κΈ°λ‘œ ν–ˆλ‹€.

 

μ „λž΅ νŒ¨ν„΄ 

ν…œν”Œλ¦Ώ νŒ¨ν„΄μ€ λΆ€λͺ¨ ν΄λž˜μŠ€μ— λ³€ν•˜μ§€ μ•ŠλŠ” ν…œν”Œλ¦Ώμ„ 두고, λ³€ν•˜λŠ” 뢀뢄을 μžμ‹ ν΄λž˜μŠ€μ—μ„œ μƒμ†ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν–ˆλ‹€. 

μ „λž΅ νŒ¨ν„΄μ€ λ³€ν•˜μ§€ μ•ŠλŠ” 뢀뢄을 Context λΌλŠ” κ°œλ…μ— 두고, λ³€ν•˜λŠ” 뢀뢄은 Strategy λΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“€μ–΄ κ΅¬ν˜„ν•΄ 문제λ₯Ό ν•΄κ²°ν•œλ‹€. 즉 상속이 μ•„λ‹ˆλΌ μœ„μž„ / κ΅¬ν˜„μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 것이닀.

κ·Έλ¦Ό 1.0

μ „λž΅νŒ¨ν„΄μ—μ„œ Context λŠ” λ¬΄μ—‡μΌκΉŒ? λ°”λ‘œ ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ ν…œν”Œλ¦Ώμ— ν•΄λ‹Ήλ˜λŠ” κ°œλ…μœΌλ‘œ, μ—¬κΈ°μ„œλŠ” λ¬Έλ§₯ μ •λ„λ‘œ μ΄ν•΄ν•˜λ©΄ λœλ‹€. κ°œλ³„ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ€ λ³€ν•  수 μžˆμ§€λ§Œ, κ·Έκ±Έ κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” 전체적인 λ¬Έλ§₯은 잘 λ³€ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, λ³€ν•˜μ§€ μ•ŠλŠ” λ‘œμ§μ„ Context 에 κ΅¬ν˜„ν•œλ‹€.

 

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

μ—¬κΈ°μ˜ call() 좔상 λ©”μ„œλ“œκ°€ λ°”λ‘œ 핡심 둜직, 즉 λ³€ν•˜λŠ” 뢀뢄에 ν•΄λ‹Ήλœλ‹€. (이전 ν¬μŠ€νŒ… - λ³€ν•˜λŠ” λΆ€λΆ„/ λ³€ν•˜μ§€ μ•ŠλŠ” λΆ€λΆ„ 을 λΆ„λ¦¬ν•˜λΌ)

Strategy λ₯Ό κ΅¬ν˜„ν•  ν΄λž˜μŠ€λŠ” call() λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•˜μ—¬ μžμ‹ λ§Œμ˜ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜λ©΄ λœλ‹€.

public interface Strategy {
    void call();
}

 

μ „λž΅μ„ κ΅¬ν˜„ν•œ StrategyLogic1, StrategyLogic2 ν΄λž˜μŠ€

@Slf4j
public class StrategyLogic1 implements Strategy {

    @Override
    public void call() {
        log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 1 μ‹€ν–‰");
    }
}


@Slf4j
public class StrategyLogic2 implements Strategy {

    @Override
    public void call() {
        log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 2 μ‹€ν–‰");
    }
}

 

Context 클래슀

Context 클래슀 내뢀에 Strategy strategy λΌλŠ” ν•„λ“œλ₯Ό 가지고 μžˆλŠ”λ°, 이 뢀뢄에 Strategy μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„μ²΄λ₯Ό μ£Όμž…ν•˜λ©΄ λœλ‹€. 

즉 λ‚΄λΆ€ ν•„λ“œμ— μ „λž΅μ„ λ³΄κ΄€ν•˜λŠ” λ°©μ‹μœΌλ‘œ, Context λŠ” Strategy μΈν„°νŽ˜μ΄μŠ€μ—λ§Œ μ˜μ‘΄ν•œλ‹€. 그말은 μ¦‰μŠ¨, Strategy 의 κ΅¬ν˜„μ²΄λ₯Ό λ³€κ²½ν•˜κ±°λ‚˜ μƒˆλ‘œ 생성해도 Context μ½”λ“œμ—λŠ” 영ν–₯을 주지 μ•ŠλŠ”λ‹€. OCP λ₯Ό 지킨 것이닀. 

μ΄λŸ¬ν•œ ν˜•νƒœλŠ” μŠ€ν”„λ§μ—μ„œ μ˜μ‘΄κ΄€κ³„ μ£Όμž…(DI)μ—μ„œ μ‚¬μš©ν•˜λŠ” 방식과 μƒν†΅ν•œλ‹€. 즉 μŠ€ν”„λ§μ˜ 의쑴 관계 μ£Όμž…μ€ μ „λž΅ νŒ¨ν„΄μ˜ μΌμ’…μœΌλ‘œ λ³Ό 수 μžˆλ‹€. 

@Slf4j
public class ContextV1 {

    final private Strategy strategy;

    // μƒμ„±μž μ£Όμž…
    public ContextV1(Strategy strategy) {
        this.strategy = strategy;
    }

    public void execute() {
        long startTime = System.currentTimeMillis();
        strategy.call(); // μœ„μž„
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime = {}", resultTime);
    }
}

κ·Έλ¦Ό 1. 1

Context1 μ΄λΌλŠ” μΈμŠ€ν„΄μŠ€μ— strategyLogic1 μ΄λΌλŠ” κ΅¬ν˜„μ²΄λ₯Ό μ£Όμž…ν•΄λ²„λ¦°λ‹€. μ˜μ‘΄μ„±μ„ μ£Όμž…ν–ˆμ§€λ§Œ ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ μƒμ†μ²˜λŸΌ, μžμ‹ ν΄λž˜μŠ€μ™€ λΆ€λͺ¨ ν΄λž˜μŠ€κ°„μ˜ κ°•λ ₯ν•œ 결합을 κ°•μ œν•˜μ§€ μ•ŠλŠ”λ‹€.

 

κ·Έλ¦Ό 1.2

 

 

μ„  쑰립, ν›„ μ‹€ν–‰

Context 의 λ‚΄λΆ€ ν•„λ“œμ— Strategy λ₯Ό 두고 μ‚¬μš©ν•˜λŠ” ν˜•νƒœλ‘œ, Context 와 Strategy λ₯Ό ν•œλ²ˆ μ‘°λ¦½ν•˜κ³  λ‚˜λ©΄ μ΄ν›„λ‘œλŠ” Context λ₯Ό μ‹€ν–‰ν•˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€. μŠ€ν”„λ§ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‘œλ”© μ‹œμ μ— μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ„ 톡해 ν•„μš”ν•œ μ˜μ‘΄κ΄€κ³„λ₯Ό λͺ¨λ‘ 맺어두고 남 후에 μ‹€μ œ μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” 것과 같은 원리닀. 

 

λ‹€λ§Œ 이 λ°©μ‹μ˜ 단점은, ν•œλ²ˆ μ‘°λ¦½ν•œ ν›„μ—λŠ” μ „λž΅μ„ λ°”κΎΈκΈ° ν•¨λ“€λ‹€λŠ” 것이닀. context1 에 이미 "λΉ„μ¦ˆλ‹ˆμŠ€ 둜직1 μ‹€ν–‰" μ΄λΌλŠ” μ „λž΅μ΄ 쑰립됐기 λ•Œλ¬Έμ—, μƒˆλ‘œμš΄ μ „λž΅μ„ μ‚¬μš©ν•˜λ €λ©΄ 또 λ‹€λ₯Έ context λ₯Ό 생성해야 ν•œλ‹€.

κ·Έλ¦Ό 1.3

< λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜λ©΄ κ·Έλ¦Ό 1. 1  처럼 번거둭게 클래슀λ₯Ό 생성할 ν•„μš”μ—†μ΄ 곧 λ°”λ‘œ μ˜μ‘΄μ„±μ„ μ£Όμž…ν•  수 μžˆμ„ λΏλ”λŸ¬, λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 ν¬ν•¨λœ 클래슀λ₯Ό 맀번 생성할 ν•„μš”κ°€ 없어진닀 >

 

 

νŒŒλΌλ―Έν„° 전달을 ν™œμš©ν•œ μ „λž΅ νŒ¨ν„΄ 

즉 "선쑰립 ν›„μ‹€ν–‰" νŒ¨ν„΄μ„ λ²—μ–΄λ‚˜, 이전엔 μƒμ„±μžλ‘œ μ£Όμž…λ°›μ€ μ „λž΅μ„ λ©”μ„œλ“œμ˜ νŒŒλΌλ―Έν„°λ‘œ 전달 λ°›λŠ” ν˜•νƒœλ‘œ λ³€κ²½ν•œ 것이닀.

/*
μ „λž΅μ„ ν•„λ“œλ‘œ 가지지 μ•ŠλŠ”λ‹€.
 */
 
@Slf4j
public class ContextV2 {

    // νŒŒλΌλ―Έν„°λ‘œ μ „λž΅μ„ μ „λ‹¬λ°›λŠ”λ‹€.
    public void execute(Strategy strategy) {
        long startTime = System.currentTimeMillis();
        strategy.call(); // μœ„μž„
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime = {}", resultTime);
    }
}

 

μ „λž΅ νŒ¨ν„΄ 적용 : νŒŒλΌλ―Έν„° ν™œμš©

이 λ°©λ²•μ˜ μž₯점은 execute() μ‹œμ , 즉 λ¬Έλ§₯이 μ‹€ν–‰λ˜λŠ” μ‹œμ μ— ν•„μš”ν•œ μ „λž΅μ„ 적절히 ꡐ체할 수 μžˆλ‹€. 이전 방식과 λΉ„κ΅ν•΄μ„œ μ›ν•˜λŠ” μ „λž΅μ„ λ”μš± μœ μ—°ν•˜κ²Œ λ³€κ²½ν•  수 μžˆλŠ” μž₯점이 μžˆλ‹€. 

@Slf4j
public class ContextV2Test {


    @Test
    void strategyV1() {
        ContextV2 contextV2 = new ContextV2();  // μ‘°λ¦½ν•˜μ§€ μ•Šμ•„μš”
        contextV2.execute(new StrategyLogic1());
        contextV2.execute(new StrategyLogic2());
    } // Context, Strategy λ₯Ό 선쑰립 ν›„ μ‹€ν–‰ 이 μ•„λ‹Œ, Context λ₯Ό μ‹€ν–‰ν•  λ•Œλ§ˆλ‹€ μ „λž΅μ„ 인수둜 μ „λ‹¬ν•œλ‹€.
    // execute μ‹œμ μ— μ—¬λŸ¬ μ „λž΅μ„ 인수둜 μ „λ‹¬ν•˜μ—¬ μœ μ—°ν•˜κ²Œ μ‹€ν–‰ κ°€λŠ₯.


    @Test
    @DisplayName("읡λͺ… 클래슀 μ‚¬μš©")
    void strategyV2() {
        ContextV2 contextV2 = new ContextV2();
        contextV2.execute(new Strategy() {
            @Override
            public void call() {
                log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 1 μ‹€ν–‰");
            }
        });
        contextV2.execute(new Strategy() {
            @Override
            public void call() {
                log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 2 μ‹€ν–‰");
            }
        });
    }


    @Test
    @DisplayName("λžŒλ‹€μ‹ μ‚¬μš©")
    void strategyV3() {
        ContextV2 contextV3 = new ContextV2();
        contextV3.execute(() -> log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 1 μ‹€ν–‰"));
        contextV3.execute(() -> log.info("λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 2 μ‹€ν–‰"));
    }
}

κ·Έλ¦Ό 1.4

 

 

정리 

두가지 λ°©μ‹μœΌλ‘œ μ „λž΅ νŒ¨ν„΄μ„ 확인해봀닀. 두 방식 쀑 μ–΄λŠ 것 ν•˜λ‚˜κ°€ μš°μ›”νžˆ μ’‹λ‹€λŠ” 건 μ•„λ‹ˆκ³ , κ°œλ°œμžκ°€ μ²˜ν•œ μƒν™©μ—μ„œ μ μ ˆν•œ 방법을 μ±„νƒν•˜λ©΄ λœλ‹€.

 

1) μƒμ„±μž μ£Όμž…μ„ ν†΅ν•œ μ „λž΅ νŒ¨ν„΄

- μ„  쑰립, ν›„ μ‹€ν–‰ λ°©μ‹μœΌλ‘œ Context λ₯Ό μ‹€ν–‰ν•˜λŠ” μ‹œμ μ— 이미 쑰립이 끝났기에, μ „λž΅μ„ 신경쓰지 μ•Šκ³  λ‹¨μˆœ μ‹€ν–‰λ§Œ ν•˜λ©΄ λœλ‹€.

 

2) νŒŒλΌλ―Έν„° μ£Όμž…μ„ ν†΅ν•œ μ „λž΅ νŒ¨ν„΄.

- μ‹€ν–‰ν•  λ•Œ λ§ˆλ‹€ μ „λž΅μ„ μœ μ—°ν•˜κ²Œ 변겨할 수 μžˆλ‹€.

- μ‹€ν–‰ν•  λ•Œ λ§ˆλ‹€ μ „λž΅μ„ 계속 μ§€μ •ν•΄μ€˜μ•Ό ν•˜λŠ” 것이 단점일 μˆ˜λ„ μžˆλ‹€ (λ²ˆκ±°λ‘œμ›€)

 

 

 

 

μ½”λ“œ 및 자료 좜처 :https://inf.run/5BUY

 

μŠ€ν”„λ§ 핡심 원리 - κ³ κΈ‰νŽΈ - μΈν”„λŸ° | κ°•μ˜

μŠ€ν”„λ§μ˜ 핡심 원리와 κ³ κΈ‰ κΈ°μˆ λ“€μ„ 깊이있게 ν•™μŠ΅ν•˜κ³ , μŠ€ν”„λ§μ„ μžμ‹ μžˆκ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€., - κ°•μ˜ μ†Œκ°œ | μΈν”„λŸ°...

www.inflearn.com