[Design Pattern] 1. singleton νŒ¨ν„΄

κ°œμš” 

  1. λ””μžμΈ νŒ¨ν„΄μ΄ 무엇인지, μ™œ μ‚¬μš©ν•˜λŠ”μ§€ μ΄ν•΄ν•œλ‹€.
  2. 싱글톀 νŒ¨ν„΄μ— λŒ€ν•΄ μ΄ν•΄ν•˜κ³ , μ–Έμ œ μ‚¬μš©ν•˜λŠ”μ§€ νŒŒμ•…ν•œλ‹€.
  3. 싱글톀 νŒ¨ν„΄μ˜ μž₯점에 λŒ€ν•΄ νŒŒμ•…ν•œλ‹€.

λ””μžμΈ νŒ¨ν„΄μ΄λž€?

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

λ””μžμΈ νŒ¨ν„΄μ΄λž€, μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό 섀계할 λ•Œ νŠΉμ • λ§₯λ½μ—μ„œ 자주 λ°œμƒν•˜λŠ” 고질적인 λ¬Έμ œλ“€μ„ ν”Όν•  수 μžˆλ„λ‘ 널리 μ•Œλ €μ§„ 해결책듀을 λ§ν•©λ‹ˆλ‹€. 

 

"바퀴λ₯Ό λ‹€μ‹œ 발λͺ…ν•˜μ§€ 마라(Don't reinvent the wheel)"

 

이 문ꡬ의 μ˜λ―ΈλŠ” 이미 λ§Œλ“€μ–΄μ Έ μžˆμ–΄μ„œ μ™„λ²½ν•œ 것을 μ²˜μŒλΆ€ν„° ꡳ이 λ‹€μ‹œ λ§Œλ“€ ν•„μš”κ°€ μ—†λ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€. λ””μžμΈ νŒ¨ν„΄μ€ 이 말을 지킬 수 μžˆλ„λ‘ ν•˜λŠ” 널리 νΌμ ΈμžˆλŠ” 해결책을 μ˜λ―Έν•˜λ©°, λ˜ν•œ νŒ€μ› μ‚¬μ΄μ˜ 징검닀리λ₯Ό μžμ²˜ν•˜μ—¬ μ˜μ‚¬ μ†Œν†΅μ„ μ›ν™œν•˜κ²Œ ν•΄μ£ΌλŠ” κ°œλ°œμžλ“€μ—κ²ŒλŠ” ꡉμž₯히 고마운 κ°œλ…μž…λ‹ˆλ‹€.

 λ””μžμΈ νŒ¨ν„΄ ꡬ쑰 

μ½˜ν…μŠ€νŠΈ 

  1. λ¬Έμ œκ°€ λ°œμƒν•˜λŠ” μ—¬λŸ¬ 상황을 κΈ°μˆ ν•˜λ©°, νŒ¨ν„΄μ΄ 적용될 수 μžˆλŠ” 상황을 μ˜λ―Έν•©λ‹ˆλ‹€.
  2. κ²½μš°μ— λ”°λΌμ„œλŠ” νŒ¨ν„΄μ΄ μœ μš©ν•˜μ§€ λͺ»ν•œ 상황을 λ‚˜νƒ€λ‚΄κΈ°λ„ ν•©λ‹ˆλ‹€. 

 

문제 

  1. νŒ¨ν„΄μ΄ μ μš©λ˜μ–΄ 해결될 ν•„μš”κ°€ μžˆλŠ” μ—¬λŸ¬ λ””μžμΈ 이슈λ₯Ό κΈ°μˆ ν•˜λ©°, ν•΄λ‹Ή λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ œμ•½ 사항과 영ν–₯λ ₯을 κ³ λ €ν•΄μ•Όλ§Œ ν•©λ‹ˆλ‹€.

 

ν•΄κ²° 

  1. 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ„λ‘ 섀계λ₯Ό κ΅¬μ„±ν•˜λŠ” μš”μ†Œλ“€κ³Ό κ·Έ μš”μ†Œλ“€ μ‚¬μ΄μ˜ 관계, μ±…μž„, ν˜‘λ ₯ 관계λ₯Ό κΈ°μˆ ν•©λ‹ˆλ‹€.
  2. 해결은 λ°˜λ“œμ‹œ ꡬ체적인 κ΅¬ν˜„ λ°©λ²•μ΄λ‚˜ 언어에 μ˜μ‘΄μ μ΄μ§€ μ•ŠμœΌλ©° λͺ¨λ“  μƒν™©μ—μ„œ 적용될 수 μžˆλŠ” μΌμ’…μ˜ κ·œμΉ™μž…λ‹ˆλ‹€.

Singleton Pattern μ΄λž€?

단 ν•˜λ‚˜μ˜ 객체λ₯Ό μƒμ„±ν•˜κ³  μƒμ„±λœ 객체λ₯Ό μ–΄λ””μ„œλ“  μ°Έμ‘°ν•  수 μžˆλ„λ‘ ν•˜λŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ ν”„λ¦°ν„° 객체와 같은 경우, λ‘κ°œ μ΄μƒμ˜ μΈμŠ€ν„΄μŠ€κ°€ ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— ν•œκ°œ μ΄μƒμ˜ 객체가 생성될 경우 μžμ›μ΄ λ‚­λΉ„λ˜κ±°λ‚˜ 버그가 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ΄λŸ¬ν•œ μƒν™©μ—μ„œ 였직 객체λ₯Ό ν•˜λ‚˜λ§Œ μƒμ„±ν•˜κ³  κ·Έ 객체λ₯Ό κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•˜λ„λ‘ ν•˜λŠ” 것이 μ‹±κΈ€ν„΄ νŒ¨ν„΄μ˜ μ£Όμš” λͺ©μ μž…λ‹ˆλ‹€.  

Singleton Pattern κ΅¬ν˜„

1
2
3
4
5
6
7
8
9
10
public class Singleton {
    private static Singleton instance; 
    private Singleton() {} 
    public static Singleton getInstance() 
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
 
 

 

private μƒμ„±μž

  1. μƒμ„±μžλ₯Ό private둜 μ§€μ •ν•œ μ΄μœ λŠ”, μ™ΈλΆ€ ν΄λž˜μŠ€μ—μ„œ ν•΄λ‹Ή 객체λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν•˜λ„둝 ν•˜κΈ° μœ„ν•΄μ„œ μž…λ‹ˆλ‹€.

instance

  1. Singleton Pattern으둜 μΈν•΄μ„œ λ§Œλ“€μ–΄μ§„ κ°μ²΄μž…λ‹ˆλ‹€.
  2. μ™ΈλΆ€ ν΄λž˜μŠ€μ—μ„œλŠ” ν•΄λ‹Ή 객체λ₯Ό μ‚¬μš©ν•˜κ²Œ 되며, private으둜 μ„ μ–Έν•˜μ—¬ μ™ΈλΆ€ ν΄λž˜μŠ€μ—μ„œ 직접 μ ‘κ·Όν•  수 없도둝 ν•©λ‹ˆλ‹€.

public static Singleton getInstance()

  1. μ™ΈλΆ€μ˜ λͺ¨λ“  ν΄λž˜μŠ€μ—μ„œ ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 객체λ₯Ό νšλ“ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. λ§Œμ•½ 객체가 아직 λ§Œλ“€μ–΄μ§€κΈ° 전이라면, 객체λ₯Ό μƒμ„±ν•˜μ—¬ λ¦¬ν„΄ν•΄μ€λ‹ˆλ‹€.
  3. λ§Œμ•½ 객체가 λ§Œλ“€μ–΄μ§„ 후라면, 이미 λ§Œλ“€μ–΄μ Έ μžˆλŠ” 객체λ₯Ό λ¦¬ν„΄ν•΄μ€λ‹ˆλ‹€.

Singleton Pattern μ‚¬μš©

1
2
3
public class OuterClass {
    Singleton instance = Singleton.getInstance();
}
 
 

μ™ΈλΆ€ ν΄λž˜μŠ€μ—μ„œ λ‹€μŒκ³Ό 같이 μ‹±κΈ€ν„΄ 객체λ₯Ό 얻어와 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Multi-Thread ν™˜κ²½μ—μ„œμ˜ Singleton Pattern

λ§Œμ•½μ— Multi-Thread ν™˜κ²½μ—μ„œ 두 개 μ΄μƒμ˜ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— getInstance() ν•¨μˆ˜μ— μ ‘κ·Όν•œλ‹€λ©΄, 두 개 μ΄μƒμ˜ 객체가 λ™μ‹œμ— 생성 될 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 상황을 막기 μœ„ν•΄μ„œλŠ” μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒμš”? 

 

classκ°€ λ‘œλ”©λ˜μ§€λ§ˆμž 객체 μƒμ„±ν•˜κΈ° 

1
2
3
4
5
6
7
public class Singleton{
    private static Singleton instance = new Singleton(); 
    private Singleton() {} 
    public static Singleton getInstance() {
        return instance; 
    }    
}
 
 

μ•„μ˜ˆ 객체λ₯Ό 미리 μƒμ„±ν•˜μ—¬ λ™μ‹œμ— μ ‘κ·Όν•˜μ—¬ 객체가 두 개 이상 μƒμ„±λ˜λŠ” 상황을 λ§‰λŠ” λ°©λ²•μž…λ‹ˆλ‹€. 동기화 λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šμ§€λ§Œ λΆˆν•„μš”ν•œ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό λ‚­λΉ„ν•˜κ²Œ λœλ‹€λŠ” 단점이 μžˆμŠ΅λ‹ˆλ‹€. 

synchronized ν‚€μ›Œλ“œ μ‚¬μš©ν•˜κΈ°

1
2
3
4
5
6
7
8
9
10
public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public synchronized static Singleton getInstance()
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
 
 

synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ getInstance() λ©”μ„œλ“œλ₯Ό λ™κΈ°ν™”ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. λ¬Όλ‘  동기화 λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šμ§€λ§Œ μˆ˜ν–‰ μ‹œκ°„μ΄ λŠλ €μ§„λ‹€λŠ” 단점이 μžˆμŠ΅λ‹ˆλ‹€.

λ‚΄λΆ€ static 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” 방법 

1
2
3
4
5
6
7
8
9
10
11
class Singleton {
    private Singleton() {}
 
    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
 
    private static class LazyHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}
 
 

 

LazyHolder κΈ°λ²•μœΌλ‘œ Singleton 클래슀의 getInstance() λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œ LazyHolder.INSTANCEλ₯Ό μ°Έμ‘°ν•˜λŠ” μˆœκ°„ classκ°€ λ‘œλ”©λ˜λ©° μ΄ˆκΈ°ν™”κ°€ μ§„ν–‰λ©λ‹ˆλ‹€. classλ₯Ό λ‘œλ”©ν•˜κ³  μ΄ˆκΈ°ν™”ν•˜λŠ” μ‹œμ μ€ thread-safeλ₯Ό 보μž₯ν•˜κΈ° λ•Œλ¬Έμ— volatileμ΄λ‚˜ synchronized같은 ν‚€μ›Œλ“œκ°€ λΆˆν•„μš” ν•˜κ²Œ λ©λ‹ˆλ‹€.

 

 

Reference

https://github.com/GimunLee/tech-refrigerator/blob/master/Design%20Pattern/Singleton%20Pattern.md

 

GimunLee/tech-refrigerator

🍰 기술 냉μž₯κ³ μž…λ‹ˆλ‹€. πŸ›’ 기술 λ©΄μ ‘ , 전곡 μ‹œν—˜ , 지식 함양 λ“± λΆ„λͺ… 도움될 κ±°μ˜ˆμš”! 🀟 - GimunLee/tech-refrigerator

github.com

https://jungwoon.github.io/java/2019/08/11/Singleton-Pattern-with-Multi-Thread/

 

λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œμ˜ 싱글톀 νŒ¨ν„΄ - Jungwoon Blog

μžλ°” λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ 싱글톀 νŒ¨ν„΄ 싱글톀 νŒ¨ν„΄ GoF(Gang of Four) λ””μžμΈ νŒ¨ν„΄ 쀑 ν•˜λ‚˜λ‘œ μƒμ„±μžκ°€ μ—¬λŸ¬ μ°¨λ‘€ ν˜ΈμΆœλ˜λ”λΌλ„ μ‹€μ œλ‘œ μƒμ„±λ˜λŠ” μΈμŠ€ν„΄μŠ€λŠ” ν•˜λ‚˜μ΄κ³ , 졜초 생성 이후에 호좜된 μƒμ„±μžλŠ” μ΅œμ΄ˆμ— μƒμ„±ν•œ 객체λ₯Ό λ¦¬ν„΄ν•˜λŠ” ν˜•νƒœ 일반적인 ν˜•νƒœ class Singleton { private static Singleton ourInstance = null; public static Singleton getInstance() { if (ourI

jungwoon.github.io