Post

Singleton Pattern

Singleton Pattern 정리

싱글톀 νŒ¨ν„΄μ΄λž€?

싱글턴은 ν΄λž˜μŠ€μ— μΈμŠ€ν„΄μŠ€κ°€ ν•˜λ‚˜λ§Œ μžˆλ„λ‘ ν•˜λ©΄μ„œ 이 μΈμŠ€ν„΄μŠ€μ— λŒ€ν•œ μ „μ—­ μ ‘κ·Ό(μ•‘μ„ΈμŠ€) 지점을 μ œκ³΅ν•˜λŠ” 생성 λ””μžμΈΒ νŒ¨ν„΄μ΄λ‹€.

즉, 데이터 λ² μ΄μŠ€μ™€ 같은 경우 ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€λ§Œμ„ κ°€μ Έμ•Ό ν•œλ‹€. 이럴 λ•Œ 싱글톀 νŒ¨ν„΄μ„ μ‚¬μš©ν•œλ‹€.(μΈμŠ€ν„΄μŠ€κ°€ 1개만 μžˆμŒμ„ 보증)

[섀계 νŒ¨ν„΄ μˆ˜μ—…μ—μ„œ]

1
2
- λ””μžμΈ νŒ¨ν„΄μ΄ μ•„λ‹Œ μ½”λ”© νŒ¨ν„΄μœΌλ‘œ λ³΄λŠ” μ‚¬λžŒλ„ 있음(경계에 속함)
- μ—¬λŸ¬ κ°€μ§€ 이유둜 μΈμŠ€ν„΄μŠ€λ₯Ό ν•˜λ‚˜λ§Œ μƒμ„±ν•˜κ³ , 클래슀λ₯Ό 톡해 참쑰만 ν•˜κ²Œν•¨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton {

    private static Singleton instance = new Singleton();
    
    private Singleton() {
        // μƒμ„±μžλŠ” μ™ΈλΆ€μ—μ„œ 호좜λͺ»ν•˜κ²Œ private 으둜 μ§€μ •ν•΄μ•Ό ν•œλ‹€.
    }

    public static Singleton getInstance() {
        return instance;
    }

    public void say() {
        System.out.println("hi, there");
    }
}

병행성

*병행성 쑰심

μ—¬κΈ° μ•„λž˜μ˜ 방법은 κ°„λ‹¨νžˆ getInstance 뿐만 μ•„λ‹ˆλΌ 병행성 ν”„λ‘œκ·Έλž˜λ°μ— λŒ€ν•΄ κ³ λ €ν•΄λ³Όλ§Œν•œ 문제λ₯Ό μ œμ‹œν•œλ‹€.

  1. Lazy Initialization

μ•„λž˜μ™€ 같이 이미 클래슀 λ‚΄μ˜ μ „μ—­λ³€μˆ˜λ‘œ 생성 β†’ μ•ˆμ“°μ΄λŠ” 경우 μžμ› λ‚­λΉ„

1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
    private static Singleton uniqueInstance = new Singleton();

    // other useful instance variables
    private Singleton() {
    }

    public static Singleton getInstance() {
        return uniqueInstance;
        // other useful methods }
    }
}
  1. Eager Initialization

ν˜Ήμ€ getInstance ν•¨μˆ˜μ— 병행성 μ½”λ“œ μΆ”κ°€ β†’ lockμ΄λ‹ˆ μ„±λŠ₯μ €ν•˜

1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
    private static Singleton uniqueInstance = new Singleton();

    // other useful instance variables
    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        return uniqueInstance;
        // other useful methods }
    }
}
  1. DCL(double checked locking) (java 1.5 μ΄μƒμ—μ„œ 보μž₯) β†’ μ„±λŠ₯ μš°μˆ˜ν•˜λ‚˜ + κ΅¬ν˜„μ΄ μ–΄λ ΅λ‹€.
1
2
3
4
5
6
7
8
9
10
public static Singleton getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}

[Java 병행성, v1.5 ~ ]

  • Synchronize: ν•΄λ‹Ή 블락에 λŒ€ν•œ μ ‘κ·Όμžμ²΄μ—μ„œ lock을 톡해 병행성 관리
  • Volatile: ν•΄λ‹Ή λ³€μˆ˜μ— λŒ€μ€‘

고렀사항

  • classλ₯Ό μ „λΆ€ staticν•˜κ²Œ, 클래슀끼리 κ³΅μœ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€λ©΄ μ‹±κΈ€ν†€μ΄λž‘ λ˜‘κ°™μ€ κΈ°λŠ₯을 μˆ˜ν–‰ν•  수 μžˆλ‹€.

ν•˜μ§€λ§Œ, 정적 μ΄ˆκΈ°ν™” λ‹¨κ³„μ—μ„œ μ—¬λŸ¬ μ—λŸ¬κ°€ λ°œμƒν•  수 있으며 λ°œμƒν•œ μ—λŸ¬λŠ” μ°ΎκΈ° νž˜λ“€λ‹€.

  • 클래슀 λ‘œλ”

[ν΄λž˜μŠ€λ‘œλ”λž€?]

μžλ°” ν΄λž˜μŠ€λ“€μ€ μ»΄νŒŒμΌλ•Œ λ‘œλ“œλ˜μ§€ μ•Šκ³ , λ™μ μœΌλ‘œ ν•„μš”ν•  λ•Œ λ‘œλ“œλœλ‹€. 클래슀 λ‘œλ”λŠ” JRE의 μΌλΆ€λ‘œμ¨Β λŸ°νƒ€μž„μ— 클래슀λ₯Ό λ™μ μœΌλ‘œ JVM에 λ‘œλ“œ ν•˜λŠ” 역할을 μˆ˜ν–‰ν•˜λŠ” λͺ¨λ“ˆμ΄λ‹€. μžλ°”μ˜ ν΄λž˜μŠ€λ“€μ€ μžλ°” ν”„λ‘œμ„ΈμŠ€κ°€ μƒˆλ‘œ μ΄ˆκΈ°ν™”λ˜λ©΄ ν΄λž˜μŠ€λ‘œλ”κ°€ μ°¨λ‘€μ°¨λ‘€ λ‘œλ”©λ˜λ©° μž‘λ™ν•œλ‹€.

[λ°œμƒν•  수 μžˆλŠ” 문제]

클래슀 λ‘œλ”κ°€ μ—¬λŸ¬ 개라면, 각기 λ‹€λ₯Έ 싱글톀 μΈμŠ€ν„΄μŠ€λ₯Ό 1κ°œμ”© μ†Œμœ ν•  수 μžˆλ‹€. μ΄λ•Œ λ¬Έμ œκ°€ λ°œμƒν•˜λ―€λ‘œ, 클래슀 λ‘œλ”λ₯Ό μ§€μ •ν•˜κ±°λ‚˜ 이λ₯Ό λ°©μ§€ν•΄μ•Ό ν•œλ‹€.

  • 직렬화와 λ¦¬ν”Œλ ‰μ…˜

https://inpa.tistory.com/entry/JAVA-β˜•-싱글톀-객체-κΉ¨λœ¨λ¦¬λŠ”-방법-역직렬화-λ¦¬ν”Œλ ‰μ…˜#μ—­μ§λ ¬ν™”λ‘œ_κΉ¨μ§€λŠ”_μ‹±κΈ€ν†€μ—μ„œ μžμ„Έν•˜κ²Œ 확인할 수 μžˆλ‹€.

  • loose coupling 원칙

싱글톀 방법을 μ‚¬μš©ν•˜λ©΄, 싱글톀 ν΄λž˜μŠ€κ°€ λ³€κ²½λ˜λ©΄ κ΄€λ ¨λœ λͺ¨λ“  클래슀λ₯Ό λ³€κ²½ν•΄μ•Ό ν•œλ‹€. 즉, λŒ€λΆ€λΆ„μ˜ ν΄λž˜μŠ€κ°€ 싱글톀 클래슀의 λ‚΄λΆ€λ₯Ό μ•Œμ•„μ•Όν•˜λ©° μ΄λŠ” λŠμŠ¨ν•œ κ²°ν•© 원칙에 μœ„λ°°λœλ‹€.

  • μ „μ—­λ³€μˆ˜μ™€μ˜ 차이

동기화λ₯Ό κ³ λ €ν•˜μ—¬ μƒμ„±ν•˜λ©΄, λ³‘ν–‰μ„±λΆ€λΆ„μ˜ 3번 ν˜Ήμ€ 2번 경우라면 μ „μ—­λ³€μˆ˜μ™€ λ‹€λ₯΄κ²Œ ν•œλ²ˆμ΄λΌλ„ μ‚¬μš©ν•΄μ•Ό μƒμ„±ν•œλ‹€. λ˜ν•œ, ν΄λž˜μŠ€μ΄κΈ°μ— μ ‘κ·Όμ œμ–΄μž λ“± μ—¬λŸ¬ μž₯점이 μžˆλ‹€.

결과적으둜?

κ·Έλž˜μ„œ λ‚˜μ˜¨ Enum μ•„λž˜μ™€ 같이 enum으둜 클래슀λ₯Ό μ§€μ •ν•œλ‹€. enum은 μžλ°”μ—μ„œλŠ” μƒμˆ˜κ°€ μ•„λ‹Œ 클래슀처럼 μ‚¬μš©ν•  수 μžˆλ‹€. λ˜ν•œ, enum은 μ‹œμž‘ μ‹œ ν•œλ²ˆλ§Œ μ΄ˆκΈ°ν™”ν•˜κΈ°μ— 싱글톀 원칙을 μ§€ν‚€λ©°, atomicν•˜κ²Œ μ²˜λ¦¬λ˜κΈ°μ— λ©€ν‹° μ“°λ ˆλ“œμ—μ„œλ„ μ•ˆμ „ν•˜λ‹€.

μ•„λž˜λŠ” ν—€λ“œνΌμŠ€νŠΈ κ΄€λ ¨ μ½”λ“œ μ˜ˆμ‹œμ΄λ‹€.

1
2
3
4
5
6
7
8
9
10
public enum Singleton {
	UNIQUE_INSTANCE;
 
	// other useful fields here

	// other useful methods here
	public String getDescription() {
		return "I'm a thread safe Singleton!";
	}
}

μ•„λž˜μ™€ 같이 μ‚¬μš©ν•˜λ©΄ λœλ‹€.

1
2
3
4
5
6
public class SingletonClient {
	public static void main(String[] args) {
		Singleton singleton = Singleton.UNIQUE_INSTANCE;
		System.out.println(singleton.getDescription());
	}
}

싱글톀 νŒ¨ν„΄μ˜ 단점

  • 싱글톀 νŒ¨ν„΄μ„ κ΅¬ν˜„ν•˜λŠ” μ½”λ“œ μžμ²΄κ°€ 많이 λ“€μ–΄κ°„λ‹€.
  • μ˜μ‘΄κ΄€κ³„μƒ ν΄λΌμ΄μ–ΈνŠΈκ°€ ꡬ체 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•œλ‹€. DIPλ₯Ό μœ„λ°˜ν•œλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈκ°€ ꡬ체 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•΄μ„œ OCP 원칙을 μœ„λ°˜ν•  κ°€λŠ₯성이 λ†’λ‹€.
  • ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€.
  • λ‚΄λΆ€ 속성을 λ³€κ²½ν•˜κ±°λ‚˜ μ΄ˆκΈ°ν™” ν•˜κΈ° μ–΄λ ΅λ‹€.
  • private μƒμ„±μžλ‘œ μžμ‹ 클래슀λ₯Ό λ§Œλ“€κΈ° μ–΄λ ΅λ‹€.
  • 결둠적으둜 μœ μ—°μ„±μ΄ λ–¨μ–΄μ§„λ‹€.
  • μ•ˆν‹°νŒ¨ν„΄μœΌλ‘œ λΆˆλ¦¬κΈ°λ„ ν•œλ‹€.
This post is licensed under CC BY 4.0 by the author.