Effective Java 아이템 3. private 생성자나 enum 타입으로 싱글턴임을 보증하라

Jae·2024년 2월 4일

Effective Java

목록 보기
4/11

싱글톤

정의

정확히 하나의 인스턴스만 생성하는 클래스로 시스템상에 유일하게 존재하는 컴포넌트를 의미한다.

구현 방법

Java 1.5 이전

전제 조건

  1. 생성자를 private로 선언한다.
  2. public static으로 유일한 인스턴스를 만들어 외부에서 접근할 수 있게 한다.

방법1. 멤버를 final 필드로 하기

public static class Doorlock {
  public static final Doorlock INSTANCE = new Doorlock(); // 1.

  private Doorlock() {}

  public void unlock() {}
}
  • 코드의 1. : 생성자는 딱 한번 호출되어 인스턴스 초기화에 사용된다.
  • 다른 생성자는 없기때문에 하나의 도어락이 생김을 보장한다.
    이 인스턴스를 사용하게 되면 변경할 방법이 없고 객체 하나만 사용하는 것임을 알 수 있다.
  • 멤버 필드만으로 싱글톤 클래스를 명확하게 알 수 있다.
    - public static final이므로 항상 동일한 인스턴스를 참조한다.
  • 클라이언트에서 사용하지 않아도 인스턴스가 항상 생성되어 메모리가 낭비된다.

방법2.

public static class Doorlock {
  // 변경된 부분 1
  private static final Doorlock INSTANCE = new Doorlock();
  // 변경된 부분 2
  public static Doorlock getInstance(){
    return INSTANCE;
  }

  private Doorlock() {}

  public void unlock() {}
}
  • 인스턴스를 생성하는 곳이 유일하고, 그 곳을 참조해서 반환하기 때문에 둘 이상의 인스턴스는 절대 생성되지 않는다.
  • 클래스의 API를 변경하지 않고 클래스에서 반환하는 싱글톤 인스턴스의 형태를 유연하게 바꿀 수 있다.
    - 팩토리 메소드에서는 유일한 인스턴스를 반환하지만, 이 메서드를 호출하는 각 스레드는 하나씩 인스턴스를 반환하도록 쉽게 수정할 수 있다.
  • 제너릭 타입으로 사용할 수도 있다.
  • 정적 팩터리의 메서드 참조를 공급자(supplier)로 사용할 수 있다.

방법 1, 2의 직렬화

  1. 클래스 선언부에 implements Serializable 추가
  2. 모든 인스턴스 필드를 trasient로 선언
  3. 역직렬화시 새로운 인스턴스 생성을 막기위해 readResolve 메서드를 추가.

Java 1.5 이후

열거형(enum) 타입 사용하기

  public enum Doorlock {
    INSTANCE;
    public void unlock() {}

  }
  • 간결하다.
  • 복잡한 직렬화나 reflection 상황에서 직렬화가 자동으로 지원되고 인스턴스가 여러 개 생기지 않도록 보장한다.
  • 가장 추천.

    참조

    Effective Java

0개의 댓글