관리 메뉴

개발그래머

Design Pattern[1] 싱글톤 패턴 본문

Java

Design Pattern[1] 싱글톤 패턴

임요환 2023. 4. 19. 20:18

싱글톤 패턴(Singleton Pattern)

  • 인스턴스를 오직 한개만 제공하는 클래스
  • 시스템 런타임, 환경 세팅에 대한 정보 등, 인스턴스가 여러개 일 때 문제가 생길 수 있는 경우 사용

naive

public class Settings {
    private static Settings instance;

    private Settings() {}

    public static Settings getInstance() {
        if (instance == null) {
            instance = new Settings();
        }

        return instance;
    }
}
  • naive(단순)하게 고려한 싱글톤 코드
  • private 생성자를 통해 new 생성자의 사용을 막음
  • public static method를 통해 객체를 생성하게 만듬
  • multi thread 환경을 고려하지 못한 싱글톤 코드임
  • 서로 다른 두개의 쓰레드가 동시에 if(instance == null)을 확인하고 다음 코드를 실행하면 서로다른 new Settings() 객체를 가지게 됨

synchronized

public class Settings {
    private static Settings instance;

    private Settings() {}

    public static synchronized Settings getInstance() {
        if (instance == null) {
            instance = new Settings();
        }

        return instance;
    }
}
  • synchronized 키워드를 사용하여 멀티 쓰레드 환경에서 안전하게 객체를 생성할 수 있음
  • synchronized 키워드는 성능을 저하 시킴

eager initialization

public class Settings {
    private static final Settings INSTANCE = new Settings();

    private Settings() {}

    public static Settings getInstance() {
        return INSTANCE;
    }
}
  • synchronized 성능 저하가 신경쓰이고 객체를 나중에 만들지 않고 객체를 생성하는 비용이 비싸지 않으면 이른 초기화(eager initialization)를 사용하여도 됨
  • 이른 초기화 자체가 단점이 될 수 있음 -> 많은 비용을 들여 생성을 했지만 사용하지 않을 경우

double checked locking

public class Settings {
    private static volatile Settings instance;

    private Settings() {}

    public static Settings getInstance() {
        if (instance == null) {
            synchronized (Settings.class) {
                if (instance == null) {
                    instance = new Settings();
                }
            }
        }

        return instance;
    }
}
  • double checked locking을 사용하여 효율적인 동기화 블럭을 만들 수 있음
  • 쓰레드가 동시에 if (instance == null)을 확인하고 다음 코드를 진행하였을 경우에만 synchronized 블록을 실행하기 때문에 모든 메서드에 synchronized가 걸려있을 때 보다 성능 저하가 적음
  • instance를 필요로 하는 시점에 만들 수 있음
  • 자바 1.5 이상에서 사용 가능한 코드
  • 코드가 복잡함

static inner class

public class Settings {

    private Settings() {}

    private static class SettingsHolder {
        private static final Settings INSTANCE = new Settings();
    }

    public static Settings getInstance() {
        return SettingsHolder.INSTANCE;
    }
}
  • 멀티 쓰레드 환경에서도 안전하고 getInstance() 메서드가 호출이 될 때 SettingsHolder.INSTANCE를 생성하기 때문에 lazy loading이 가능한 코드

실무에서 사용하는 싱글톤 예제

  • java.lang.Runtime
  • ApplicationContext 내부에서 유일한 객체를 보장함(스프링 빈) -> 엄밀히 말하면 싱글톤 패턴과는 좀다름, 싱글톤 스코프
  • 다른 디자인 패턴(빌더, 퍼사드, 추상 팩토리 등) 구현체의 일부로 사용하기도 함