본문으로 바로가기

싱글톤 패턴 (Singleton)

category 디자인패턴 2022. 5. 19. 17:43

싱글톤 패턴: 인스턴스를 1개만 만들어서 사용하는 패턴 

인스턴스가 하나만 존재해야 할 때 ( 환경설정과 같은 ) 사용할 수 있다. 

메모리 측면에서 한번만 생성하기 때문에 낭비를 막을 수 있고 클래스 간 데이터 공유에 용이하다.

 

인스턴스를 동시에 접근하게 될 때(멀티 쓰레드 등)를 유의해서 설계해야한다.

 

 

 

싱글톤 패턴을 구현하는 방법

 

1. Private 생성자

public class Singleton {
	private static Singleton instance;
    
	private Singleton() {};
    
    public static Singleton getInstance() {
    	if (instance == null) {
        	instance = new Singleton();
          }
    	return instance;
     }
}

private 생성자를 통해 외부에서 생성하는 것을 막을 수 있다. 

getInstance()를 통해 Singleton 객체에 접근할 수 있고 해당 instance는 내부적으로 생성하도록 한다. 

 

위 예제는 멀티 쓰레드 환경에서 safe하지 않다. 쓰레드 1이 getInstance를 호출하여 new를 실행하기 전에 쓰레드 2가 getInstance에 접근한다면 서로 다른 Instance가 생성되게 된다. 

 

public class Singleton {
	private static Singleton instance;
    
	private Singleton() {};
    
    public static synchronized Singleton getInstance() {
    	if (instance == null) {
        	instance = new Singleton();
          }
    	return instance;
     }
}

synchronized 키워드를 사용하여 동시에 생성되는 일을 막을 수 있다. 

 

 

혹은, 

 

이른 초기화 (eager initialization)

public class Singleton {
	private static Singleton instance = new Singleton(); 
    
	private Singleton() {};
    
    public static Singleton getInstance() {
    	return instance;
     }
}

인스턴스 생성에 큰 자원이 들지 않는다면 미리 만들어 놓는 방법이 있다. 

 

static inner 클래스 사용

public class Singleton {
	private Singleton() {};
    
    private static class SingletonHolder {
    	private static final Singleton INSTANCE = new Singletone();
    }
    
    public static Singleton getInstance() {
    	return Singleton.INSTANCE;
    }
}

static inner 클래스를 사용한다면 멀티 쓰레드 환경에서 안전하고

인스턴스가 사용되는 시점에서 생성될 수 있다. 

 

혹은 Enum 타입으로 싱글톤을 구현할 수 있다.