item 3 dodo4513 - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

μ•„μ΄ν…œ3 private μƒμ„±μžλ‚˜ μ—΄κ±° νƒ€μž…μœΌλ‘œ μ‹±κΈ€ν„΄μž„μ„ λ³΄μ¦ν•˜λΌ

μ‹±κΈ€ν„΄?

  • μ‹±κΈ€ν„΄(singleton)μ΄λž€ μΈμŠ€ν„΄μŠ€λ₯Ό 였직 ν•˜λ‚˜λ§Œ 생성할 수 μžˆλŠ” 클래슀λ₯Ό λ§ν•œλ‹€.
  • μ‹±κΈ€ν„΄μ˜ μ „ν˜•μ μΈ μ˜ˆλ‘œλŠ” ν•¨μˆ˜μ™€ 같은 λ¬΄μƒνƒœ(stateless) κ°μ²΄λ‚˜ 섀계상 μœ μΌν•΄μ•Ό ν•˜λŠ” μ‹œμŠ€ν…œ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ“€ 수 μžˆλ‹€.
  • 클래슀λ₯Ό μ‹±κΈ€ν„΄μœΌλ‘œ λ§Œλ“€λ©΄ 이λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό ν…ŒμŠ€νŠΈν•˜κΈ°κ°€ μ–΄λ €μ›Œμ§ˆ 수 μžˆλ‹€. νƒ€μž…μ„ μΈν„°νŽ˜μ΄μŠ€λ‘œ μ •μ˜ν•œ λ‹€μŒ κ·Έ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ„œ λ§Œλ“  싱글턴이 μ•„λ‹ˆλΌλ©΄ μ‹±κΈ€ν„΄ μΈμŠ€ν„΄μŠ€λ₯Ό κ°€μ§œ(mock) κ΅¬ν˜„μœΌλ‘œ λŒ€μ²΄ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

싱글턴을 λ§Œλ“œλŠ” 방식

public static final ν•„λ“œ λ°©μ‹μ˜ μ‹±κΈ€ν„΄

public class Elvis {

    public static final Elvis INSTANCE = new Elvis();

    private Elvis() {...}
}

  • private μƒμ„±μžλŠ” public static final ν•„λ“œμΈ Elvis.INSTANCEλ₯Ό μ΄ˆκΈ°ν™”ν•  λ•Œ λ”± ν•œ 번만 ν˜ΈμΆœλœλ‹€. publicμ΄λ‚˜ protected μƒμ„±μžκ°€ μ—†μœΌλ―€λ‘œ Elvis ν΄λž˜μŠ€κ°€ μ΄ˆκΈ°ν™”λ  λ•Œ λ§Œλ“€μ–΄μ§„ μΈμŠ€ν„΄μŠ€κ°€ 전체 μ‹œμŠ€ν…œμ—μ„œ ν•˜λ‚˜λΏμž„μ΄ 보μž₯λœλ‹€.

  • μ˜ˆμ™ΈλŠ” 단 ν•œ 가지, κΆŒν•œμ΄ μžˆλŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” λ¦¬ν”Œλ ‰μ…˜ API(μ•„μ΄ν…œ 65)인 AccessibleObject.setAccessible을 μ‚¬μš©ν•΄ private μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€. μ΄λŸ¬ν•œ 곡격을 λ°©μ–΄ν•˜λ €λ©΄ μƒμ„±μžλ₯Ό μˆ˜μ •ν•˜μ—¬ 두 번째 객체가 μƒμ„±λ˜λ € ν•  λ•Œ μ˜ˆμ™Έλ₯Ό λ˜μ§€κ²Œ ν•˜λ©΄ λœλ‹€.

  • public ν•„λ“œ λ°©μ‹μ˜ 큰 μž₯점은 ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ μ‹±κΈ€ν„΄μž„μ΄ API에 λͺ…λ°±νžˆ λ“œλŸ¬λ‚œλ‹€λŠ” 것이닀. public static ν•„λ“œκ°€ finalμ΄λ‹ˆ μ ˆλŒ€λ‘œ λ‹€λ₯Έ 객체λ₯Ό μ°Έμ‘°ν•  수 μ—†λ‹€. 두 번째 μž₯점은 λ°”λ‘œ 간결함이닀.

정적 νŒ©ν„°λ¦¬ λ°©μ‹μ˜ μ‹±κΈ€ν„΄

public class Elvis {

    private static final Elvis INSTANCE = new Elvis();

    private Elvis() {...}

    public static Elvis getInstance() { return INSTANCE; }
}
  • Elvis.getInstanceλŠ” 항상 같은 객체의 μ°Έμ‘°λ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ 제2의 Elvis μΈμŠ€ν„΄μŠ€λž€ κ²°μ½” λ§Œλ“€μ–΄μ§€μ§€ μ•ŠλŠ”λ‹€(μ—­μ‹œ λ¦¬ν”Œλ ‰μ…˜μ„ ν†΅ν•œ μ˜ˆμ™ΈλŠ” λ˜‘κ°™μ΄ μ μš©λœλ‹€).
  • 정적 νŒ©ν„°λ¦¬ λ°©μ‹μ˜ 첫 번째 μž₯점은 (마음이 λ°”λ€Œλ©΄) APIλ₯Ό 바꾸지 μ•Šκ³ λ„ 싱글턴이 μ•„λ‹ˆκ²Œ λ³€κ²½ν•  수 μžˆλ‹€λŠ” 점이닀. μœ μΌν•œ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λ˜ νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ (μ˜ˆμ»¨λŒ€) ν˜ΈμΆœν•˜λŠ” μŠ€λ ˆλ“œλ³„λ‘œ λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€λ₯Ό λ„˜κ²¨μ£Όκ²Œ ν•  수 μžˆλ‹€.
  • 두 번째 μž₯점은 μ›ν•œλ‹€λ©΄ 정적 νŒ©ν„°λ¦¬λ₯Ό μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν„°λ¦¬λ‘œ λ§Œλ“€ 수 μžˆλ‹€λŠ” 점이닀(μ•„μ΄ν…œ 30).
  • μ„Έ 번째 μž₯점은 정적 νŒ©ν„°λ¦¬μ˜ λ©”μ„œλ“œ μ°Έμ‘°λ₯Ό κ³΅κΈ‰μž(supplier)둜 μ‚¬μš©ν•  수 μžˆλ‹€λŠ” 점이닀.
  • μœ„ μž₯점듀이 ꡳ이 ν•„μš”ν•˜μ§€ μ•Šλ‹€λ©΄ public ν•„λ“œ 방식이 μ’‹λ‹€.

μ—΄κ±° νƒ€μž… λ°©μ‹μ˜ μ‹±κΈ€ν„΄: λ°”λžŒμ§ν•œ 방법

public enum Elvis {
    INSTANCE;
}
  • public ν•„λ“œ 방식과 λΉ„μŠ·ν•˜μ§€λ§Œ, 더 κ°„κ²°ν•˜κ³ , μΆ”κ°€ λ…Έλ ₯ 없이 직렬화할 수 있고, 심지어 μ•„μ£Ό λ³΅μž‘ν•œ 직렬화 μƒν™©μ΄λ‚˜ λ¦¬ν”Œλ ‰μ…˜ κ³΅κ²©μ—μ„œλ„ 제2의 μΈμŠ€ν„΄μŠ€κ°€ μƒκΈ°λŠ” 일을 μ™„λ²½νžˆ 막아쀀닀. 쑰금 λΆ€μžμ—°μŠ€λŸ¬μ›Œ 보일 μˆ˜λŠ” μžˆμœΌλ‚˜ λŒ€λΆ€λΆ„ μƒν™©μ—μ„œλŠ” μ›μ†Œκ°€ ν•˜λ‚˜λΏμΈ μ—΄κ±° νƒ€μž…μ΄ 싱글턴을 λ§Œλ“œλŠ” κ°€μž₯ 쒋은 방법이닀.
  • λ§Œλ“€λ €λŠ” 싱글턴이 Enum μ™Έμ˜ 클래슀λ₯Ό 상속해야 ν•œλ‹€λ©΄ 이 방법은 μ‚¬μš©ν•  수 μ—†λ‹€.