book review/Effective java

[Effective Java] Item 3. 생성자나 열거 타입으로 싱글턴임을 보증하라

dobidugi 2024. 2. 1. 10:37

싱글턴 ( Singleton )

 

싱글턴이란 인스턴스를 오직  하나만 생성할 수 있는 클래스를 말하며 만들어진 값은 오직 시스템상에서 하나만 존재해야한다.

 

싱글턴으로 만들고 사용하기

싱글턴으로 만드는 방식은 크게 세가지 방식이 있다.

1. public static 맴버 변수 사용

public class Single {
  public static final Object INSTANCE = new Object();
  private Single() {
  }
}
public class Main {
  public static void main(String[] args) {
    Object obj1 = Single.INSTANCE;
    Object obj2 = Single.INSTANCE;
    Object obj = new Object();
    System.out.println(obj1 == obj2); // true
    System.out.println(obj1 == obj); // false
  }
}

 

위처럼 public static 맴버 변수를 생성하면 처음 Single.INSTANCE에 접근할때 priate 생성자가 딱 한번 호출되며 싱글턴임을 보장한다.

2. 정적 팩터리 메서드 이용한 public static 메서드 사용 

public class Single {
  private static final Object INSTANCE = new Object();
  private Single() {
  }

  public static Object getInstance() {
    return INSTANCE;
  }
}
public class Main {
  public static void main(String[] args) {
    Object obj1 = Single.getInstance();
    Object obj2 = Single.getInstance();
    Object obj = new Object();
    System.out.println(obj1 == obj2); // true
    System.out.println(obj1 == obj); // false
  }
}

외부에서 INSTANCE에 직접 접근 못하게 private 권한을 주고 public static 메서드인 getInstance() 를 호출해 매번 같은 인스턴스를 얻어 올 수 있다.

 

3. 원소가 하나인 열거타입을 선언하기.

public 필드 방식과 비슷하지만, 더 간결하고 추가 노력 없이 직렬화할 수 있으며 위에 방식들은 리플렉션 공격으로 인해  제 2의 인스턴스가 생성될 수 있으나,  이 방법은 리플렉션 공격에도 제 2번째 인스턴스가 생기는것을 방지해준다.

public enum Single {
  INSTANCE;

  public String getName() {
    return "Single";
  }
}
public class Main {
  public static void main(String[] args) {
    String v1 = Single.INSTANCE.getName();
    String v2 = Single.INSTANCE.getName();
    System.out.println(v1 == v2); // true
  }
}

다만 만드려는 싱글턴이 Enum 외의 클래스에 상속해야한다면 이 방법은 사용할 수 없다.