포슀트

Enum νŒŒν—€μΉ˜κΈ° 🧹

Enum νŒŒν—€μΉ˜κΈ° 🧹

Enum 🧾

Enum이 μƒκ²¨λ‚œ 이유

본격적으둜 Enum이 무엇인지 μ•Œμ•„λ³΄κΈ° 전에, μ™œ Enum이 λ“±μž₯ν•˜κ²Œ λ˜μ—ˆλŠ”μ§€λ₯Ό λ¨Όμ € μ•Œμ•„λ³΄μž πŸ˜›

λΉ„μ¦ˆλ‹ˆμŠ€ μš”κ΅¬μ‚¬ν•­

μ‚¬μš©μžλŠ” λ‹€μ–‘ν•œ 결제 μˆ˜λ‹¨μ„ 선택할 수 있으며, 결제 방식에 따라 μ„œλ‘œ λ‹€λ₯Έ μ „λž΅μ΄ μ‹€ν–‰λœλ‹€. ν˜„μž¬ μ œκ³΅λ˜λŠ” 결제 μˆ˜λ‹¨μ€ λ‹€μŒκ³Ό κ°™λ‹€:

  • kakao : 카카였페이λ₯Ό 톡해 결제
  • naver : λ„€μ΄λ²„νŽ˜μ΄λ₯Ό 톡해 결제
  • bad : λΆˆμ•ˆμ •ν•œ ν…ŒμŠ€νŠΈμš© 결제 μˆ˜λ‹¨ 결제 μˆ˜λ‹¨μ„ μž…λ ₯ν•˜λ©΄, ν•΄λ‹Ή 방식에 λ§žλŠ” 결제 μ „λž΅ 객체λ₯Ό 생성해야 ν•œλ‹€.
  • μ •μ˜λ˜μ§€ μ•Šμ€ 결제 μˆ˜λ‹¨μ„ μž…λ ₯ν•  경우 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

πŸ” λ¬Έμžμ—΄ 기반 방식

μ‚¬μš©μžκ°€ μ„ νƒν•œ 결제 μˆ˜λ‹¨μ— 따라 결제 μˆ˜λ‹¨μ„ μ œκ³΅ν•˜λŠ” 클래슀λ₯Ό λ§Œλ“€μ–΄λ³΄μž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# StrategyFactory
public class StrategyFactory {
    public static PayStrategy of(String payOption, int amount){
        if("kakao".equals(payOption)){
            return new KakaoStrategy(payOption, amount);
        } else if("naver".equals(payOption)){
            return new NaverStrategy(payOption, amount);
        } else if("bad".equals(payOption)){
            return new BadStrategy(payOption, amount);
        } else {
            throw new IllegalArgumentException("ν•΄λ‹Ή μ „λž΅μ΄ μ—†μŠ΅λ‹ˆλ‹€.");
        }
    }
}

⚠️ 문제점

  • μ˜€νƒ€μ— μ·¨μ•½ : "KAKAO", "kakao"λ“± λ‹€μ–‘ν•œ ν‘œκΈ°λ‘œ μž…λ ₯ κ°€λŠ₯ -> 였λ₯˜ λ°œμƒ
  • 컴파일 νƒ€μž„ 검증 λΆˆκ°€ : 잘λͺ»λœ λ¬Έμžμ—΄λ„ λŸ°νƒ€μž„μ „κΉŒμ§€λŠ” μ•Œ 수 μ—†μŒ
  • 디버깅이 어렀움 : λ¬Έμ œκ°€ λ°œμƒν•΄λ„ 원인을 μ°ΎκΈ° 어렀움

βœ… λ¬Έμžμ—΄ μƒμˆ˜ μ‚¬μš©(쑰금 λ‚˜μ•„μ§„ 방식)

1
2
3
4
5
6
7
# PayOption
public class PayOption {
    public static final String KAKAO = "KAKAO";
    public static final String NAVER = "NAVER";
    public static final String BAD = "BAD";
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# StrategyFactory
public class StrategyFactory {
    public static PayStrategy of(String payOption, int amount){
        if(PayOption.KAKAO.equals(payOption)){
            return new KakaoStrategy(payOption, amount);
        } else if(PayOption.NAVER.equals(payOption)){
            return new NaverStrategy(payOption, amount);
        } else if(PayOption.BAD.equals(payOption)){
            return new BadStrategy(payOption, amount);
        } else {
            throw new IllegalArgumentException("ν•΄λ‹Ή μ „λž΅μ΄ μ—†μŠ΅λ‹ˆλ‹€.");
        }
    }
}

πŸ‘ κ°œμ„ μ 

  • μƒμˆ˜λ₯Ό 톡해 λ¬Έμžμ—΄ μž…λ ₯보닀 μ•ˆμ •μ„± ν–₯상
  • 잘λͺ»λœ μƒμˆ˜λͺ…을 μž…λ ₯ν•˜λ©΄ 컴파일 νƒ€μž„μ— 였λ₯˜ λ°œμƒ

⚠️ 문제점

  • μ—¬μ „νžˆ String νƒ€μž…μ΄λ―€λ‘œ, 잘λͺ»λœ λ¬Έμžμ—΄ μž…λ ₯ κ°€λŠ₯성은 남아 있음
  • λˆ„κ΅°κ°€ μ‹€μˆ˜λ‘œ PayOption.KAKAO λŒ€μ‹  "kakao" μž…λ ₯ν•˜λ©΄ 검증 λΆˆκ°€
  • StrategyFactory.of(String payOption, int amount) λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” μž…μž₯에선 μ˜¬λ°”λ₯Έ 값이 무엇인지 μ•ŒκΈ° 어렀움

πŸ” νƒ€μž… μ•ˆμ „ μ—΄κ±°ν˜• νŒ¨ν„΄

String을 μ•„μ˜ˆ μ“°μ§€ μ•Šκ³ , 사전에 μ •μ˜λœ 객체만 μ‚¬μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€λ©΄ μ–΄λ–¨κΉŒ?

1
2
3
4
5
6
7
8
# PayOption
public class PayOption {
    private PayOption(){}
    public static final PayOption KAKAO = new PayOption();
    public static final PayOption NAVER = new PayOption();
    public static final PayOption BAD = new PayOption();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# StrategyFactory
public class StrategyFactory {
    public static PayStrategy of(PayOption payOption, int amount){
        if(payOption == PayOption.KAKAO){
            return new KakaoStrategy(payOption, amount);
        } else if(payOption == PayOption.NAVER){
            return new NaverStrategy(payOption, amount);
        } else if(payOption == PayOption.BAD){
            return new BadStrategy(payOption, amount);
        } else {
            throw new IllegalArgumentException("ν•΄λ‹Ή μ „λž΅μ΄ μ—†μŠ΅λ‹ˆλ‹€.");
        }
    }
}

πŸ‘ κ°œμ„ μ 

  • ==으둜 λΉ„κ΅ν•˜λ―€λ‘œ μ˜€νƒ€ κ±±μ • X
  • νƒ€μž…μœΌλ‘œ μ œν•œ -> 잘λͺ»λœ κ°’ μž…λ ₯ λΆˆκ°€
  • 데이터 일관성 보μž₯

⚠️ 문제점

  • 직접 κ΅¬ν˜„ν•΄μ•Όν•  μ½”λ“œκ°€ 많음
  • private μƒμ„±μž λ“±μ˜ νŒ¨ν„΄μ„ 반볡적으둜 μž‘μ„±ν•΄μ•Ό 함

πŸ† μ΅œμ’… κ°œμ„  : Java Enum ν™œμš©

μžλ°”μ—μ„œλŠ” μœ„μ²˜λŸΌ λ³΅μž‘ν•œ κ΅¬ν˜„μ„ λ‹¨μˆœν™”ν•  수 μžˆλ„λ‘ Enum을 μ œκ³΅ν•œλ‹€.
이제 Enum을 ν™œμš”ν•˜μ—¬ μ „λž΅μ„ μ•ˆμ „ν•˜κ³  νŽΈλ¦¬ν•˜κ²Œ κ΄€λ¦¬ν•΄λ³΄μž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# PayOtion Enum
public enum PayOption {
  KAKAO {
    @Override
    public PayStrategy createStrategy(int amount) {
      return new KakaoStrategy(this, amount);
    }
  },
  NAVER {
    @Override
    public PayStrategy createStrategy(int amount) {
      return new NaverStrategy(this, amount);
    }
  },
  BAD {
    @Override
    public PayStrategy createStrategy(int amount) {
      return new BadStrategy(this, amount);
    }
  };

  public abstract PayStrategy createStrategy(int amount);
}
1
2
3
4
5
6
# StrategyFactory
public class StrategyFactory {
    public static PayStrategy of(PayOption payOption, int amount){
       return payOption.createStrategy(amount);
    }
}
1
2
3
4
5
6
7
8
# PayMain
public class PayMain {
    public static void main(String[] args) {
        PayStrategy payment = StrategyFactory.of(PayOption.KAKAO, 1000);
        payment.processPay();
    }
}

Enum λ‚΄λΆ€μ—μ„œ μ „λž΅μ„ μƒμ„±ν•œ 이유

각 Enum μƒμˆ˜(KAKAO, NAVER, BAD) κ°€ κ³ μœ ν•œ μ „λž΅ 생성 방식을 κ°€μ§€κ³  μžˆμœΌλ―€λ‘œ, switch, if-else 없이도 λ‹€ν˜•μ„±μ„ 톡해 κΉ”λ”ν•˜κ²Œ λ™μž‘μ„ μ •μ˜ν•  수 μžˆλ‹€.

μž₯점

  • νƒ€μž… μ•ˆμ •μ„± 보μž₯ : μ •μ˜λœ enum κ°’ μ™Έμ—λŠ” μ‚¬μš© λΆˆκ°€
  • switch/if 없이 λ™μž‘ μ •μ˜ κ°€λŠ₯
  • μ½”λ“œ 응집도 ν–₯상 : μ „λž΅ λ‘œμ§μ„ enum μ•ˆμ— 넣을 수 있음
  • OCP(개방-폐쇄 원칙) 만쑱 : μƒˆλ‘œμš΄ 결제 방식 μΆ”κ°€ μ‹œ κΈ°μ‘΄ μ½”λ“œ 변경없이 enumμ—λ§Œ μΆ”κ°€ν•˜λ©΄ 됨
이 κΈ°μ‚¬λŠ” μ €μž‘κΆŒμžμ˜ CC BY 4.0 λΌμ΄μ„ΌμŠ€λ₯Ό λ”°λ¦…λ‹ˆλ‹€.

Β© kunhee. 일뢀 ꢌ리 보유

Powered by Jekyll with Chirpy theme