싱글톤 패턴(Singleton Pattern)

uglyduck.dev·2020년 9월 20일
0

개념 모아 🗂

목록 보기
26/40

정의

싱글톤(Singleton Pattern) 패턴은 인스턴스가 오직 하나만 생성되는 것을 보장하고 어디에서든 이 인스턴스에 접근할 수 있도록 하는 디자인 패턴중에 하나이다. 수학 이론에서의 싱글톤은 '단 하나의 원소만을 가진 집합'이라고 기술되어있다. 하나의 인스턴스만 생성하는 책임이 있으며 유일한 메서드를 통해 모든 클라이언트에게 동일한 인스턴스를 반환하는 작업을 수행한다. 

구현 예시

몇 개의 예제를 통해 싱글톤 패턴 구현 방법을 알아보자.

1. Eager initialization(이른 초기화)

싱글톤 클래스의 인스턴스는 클래스 로딩 시에 생성되며, 이것은 싱글톤 클래스를 만들 수 있는 가장 쉬운 방법이지만 클라이언트 애플리케이션이 이 클래스를 사용하지 않더라도 인스턴스가 생성되는 단점이 있다.

package com.pattern.singleton;

public class EagerInitializedSingleton {
    
    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
    
    //클라이언트 응용 프로그램이 생성자를 사용하지 않도록 하는 개인 생성자
    private EagerInitializedSingleton(){}

    public static EagerInitializedSingleton getInstance(){
        return instance;
    }
}
  • 싱글톤 클래스가 많은 자원을 사용하지 않을 경우 사용하기 좋다. 하지만 대부분의 시나리오에서는 파일 시스템, 데이터베이스 연결 등과 같은 자원에 대해 싱글톤 클래스가 생성된다. 사용자가 getInstance 메소드를 호출하지 않는 경우를 제외하고 인스턴스 생성을 피해야 한다. 이른 초기화 패턴방법은 예외 처리를 위한 어떠한 옵션도 제공하지 않는다.

2. Static block initialization(정적 블록 초기화)

정적 블록 초기화 구현은 예외 처리를 위한 옵션을 제공하는 정적 블록에 클래스의 인스턴스가 생성된다는 점을 제외하고는 이른 초기화 방법과 유사하다.

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;
    }
}
  • 이른 초기화 및 정적 블록 초기화 방법 모두 인스턴스를 사용하기 전에 생성하며 이는 사용하기에 가장 좋은 방법이 아니다. 

3. Lazy Initialization(게으른 초기화)

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;
    }
}
  • 위의 구현은 단일 스레드 환경의 경우 잘 작동하지만 다중 스레드의 경우 여러 스레드가 동시에 조건 내에 있으면 문제가 발생할 수 있다. 

4. Thread Safe Singleton(안전한 스레드 처리 방식)

메서드 동기화를 이용하여 한 번에 하나의 스레드만 이 방법을 실행할 수 있도록 하는 것이다. 

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

profile
시행착오, 문제해결 그 어디 즈음에.

0개의 댓글