디자인 패턴 : Singleton

정의

클래스에 대한 인스턴스를 하나로 제한하는 패턴

특징

  • 인스턴스의 개수가 1개임을 보장
  • access point 제한
  • 유일한 인스턴스이면서 서브 클래싱으로 확장을 지원

예제코드

생성자를 은닉시키고, 객체 생성을 제한하여 인스턴스가 1개임을 보장하는 것에 초점을 맞춘다.

간단한 싱글톤
thread-safe 요구사항이 없다면 아래와 같은 구현으로 충분하다.

final class BasicSingleton {
  private static BasicSingleton instance;

  private BasicSingleton() {};

  // thread non safe
  public static BasicSingleton getInstance() {
    if (instance == null) {
      instance = new BasicSingleton();
    }
    return instance;
  }
}


안전한 싱글톤
thread safe 요구사항이 있다면 생성자 구현에 좀현 더 신경을 써야한다.

final class ThreadSafeSingleton {

  private static ThreadSafeSingleton instance;

  private ThreadSafeSingleton() {}

  public static ThreadSafeSingleton getInstance() {
    if (instance == null) {
      safetyInitialize();
    }
    return instance;
  }

  private static final Object _lock = new Object();
  private static void safetyInitialize() {
    synchronized (_lock) {
      if (instance == null) {
        instance = new ThreadSafeSingleton();
      }
    }
  }
}


클래스 로더를 활용한 방법
객체 생성을 inner class 에게 위임하여 초기화 시점을 제어

final class ThreadSafeSingleton2 {

  public static ThreadSafeSingleton2 getInstance() {
    return Inner.INSTANCE;
  }

  private static final class Inner {
    static final ThreadSafeSingleton2 INSTANCE = new ThreadSafeSingleton2();
  }
}


서브클래싱을 지원하는 싱글톤

abstract class SuperSingleton {

  private static final InstanceRegistry INSTANCE_REGISTRY = new InstanceRegistry();

  protected SuperSingleton() {}

  protected static void register(String name, SuperSingleton singleton) {
    INSTANCE_REGISTRY.addRegistry(name, singleton);
  }

  public static SuperSingleton getInstance() {
    SuperSingleton lookupInstance = defaultLookup();
    if (lookupInstance == null) {
      throw new IllegalStateException();
    }
    return lookupInstance;
  }

  private static SuperSingleton defaultLookup() {
    return lookup("default");
  }

  public static SuperSingleton lookup(String name) {
    return INSTANCE_REGISTRY.lookup(name);
  }

  private static class InstanceRegistry {
    private static final Map<String, SuperSingleton> REGISTRY = new HashMap<>();

    void addRegistry(String name, SuperSingleton instance) {
      if (REGISTRY.get(name) != null) {
        throw new IllegalStateException();
      }
      REGISTRY.put(name, instance);
    }

    SuperSingleton lookup(String name) {
      return REGISTRY.get(name);
    }
  }
}

예제코드
예제코드 테스트

참고자료

GoF의 디자인 패턴 p181 - p190

태그:

Back to Top ↑

댓글남기기