싱글톤(Singleton Pattern) 패턴은 인스턴스가 오직 하나만 생성
되는 것을 보장하고 어디에서든 이 인스턴스에 접근
할 수 있도록 하는 디자인 패턴중에 하나이다. 수학 이론에서의 싱글톤은 '단 하나의 원소만을 가진 집합'
이라고 기술되어있다. 하나의 인스턴스만 생성하는 책임
이 있으며 유일한 메서드를 통해 모든 클라이언트에게 동일한 인스턴스를 반환
하는 작업을 수행한다.
몇 개의 예제를 통해 싱글톤 패턴 구현 방법을 알아보자.
싱글톤 클래스의 인스턴스는 클래스 로딩 시에 생성되며, 이것은 싱글톤 클래스를 만들 수 있는 가장 쉬운 방법이지만 클라이언트 애플리케이션이 이 클래스를 사용하지 않더라도 인스턴스가 생성되는 단점이 있다.
package com.pattern.singleton;
public class EagerInitializedSingleton {
private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
//클라이언트 응용 프로그램이 생성자를 사용하지 않도록 하는 개인 생성자
private EagerInitializedSingleton(){}
public static EagerInitializedSingleton getInstance(){
return instance;
}
}
많은 자원을 사용하지 않을 경우
사용하기 좋다. 하지만 대부분의 시나리오에서는 파일 시스템, 데이터베이스 연결 등과 같은 자원에 대해 싱글톤 클래스가 생성된다. 사용자가 getInstance 메소드를 호출하지 않는 경우를 제외하고 인스턴스 생성을 피해야 한다. 이른 초기화 패턴방법은 예외 처리를 위한 어떠한 옵션도 제공하지 않는다.정적 블록 초기화 구현은 예외 처리를 위한 옵션을 제공하는 정적 블록에 클래스의 인스턴스가 생성된다는 점을 제외하고는 이른 초기화 방법과 유사하다.
package com.pattern.singleton;
public class StaticBlockSingleton {
private static StaticBlockSingleton instance;
private StaticBlockSingleton(){}
//예외 처리를 위한 정적 블록 초기화
static{
try{
instance = new StaticBlockSingleton();
}catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
}
public static StaticBlockSingleton getInstance(){
return instance;
}
}
package com.pattern.singleton;
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){}
public static LazyInitializedSingleton getInstance(){
if(instance == null){
instance = new LazyInitializedSingleton();
}
return instance;
}
}
메서드 동기화를 이용하여 한 번에 하나의 스레드만 이 방법을 실행할 수 있도록 하는 것이다.
package com.pattern.singleton;
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){}
public static synchronized ThreadSafeSingleton getInstance(){
if(instance == null){
instance = new ThreadSafeSingleton();
}
return instance;
}
}
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
Reference
JournalDev, "Java Singleton Design Pattern Best Practices with Examples", https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples(2020.04.19)
정인상,채흥석, 『JAVA 객체 지향 디자인 패턴』, 한빛미디어(2014.4.2), 201p