EJ2E Item 3. 싱글톤 속성은 private 성성자 또는 enum 타입으로

싱글톤은 객체를 딱 한번만 생성하는 클래스.

1.5 전에 싱글톤을 구현하는 방법은 두 개였다. 둘 다 private 생성자와 public static 멤버를 노출한다.

첫 번째 방법: public static filed

public class Elvis {
  public static final Elvis INSTANCE = new Elvis();
  private Elvis(){…}
  …
}

private 생성자는 딱 한 번 static final 필드인 Elvis.INSTANCE를 초기화할 때만 호출한다. 한 가지 주의 할 것이 있는데…

a privileged client can invoke the private constructor reflectively
(Item 53) with the aid of the AccessibleObject.setAccessible method

이 부분 잘 모르겠슴.

두 번째 방법: public static factory method

public class Elvis {
  private static final Elvis INSTANCE = new Elvis();
  private Elvis(){…}
  public static Elvis getInstance() { return INSTANCE; }
  …
}

위에서 잘 모르는 부분의 문제가 이렇게 하면 발생하지 않아. (OSAF도 이런식으로 싱글톤을 만들었쥐.) 좀 더 유연하게 변경할 수 있다. Generic 타입을 고려할 수 있다.(Item 27) 이것도 모르겠군.

위의 두 가지 방법은 Serializable 하지 못한다. (static 필드는 직렬화 안 되니깐) 따라서 모든 객체 필드를 transient로 선언하거나 readResolve 메소드(Item 77)를 제공해야 한다.

세 번째 방법: Enum singleton

1.5 부터 사용할 수 있는 싱글톤 구현 방법. 캬.. 드디어 새로운 방법 등장이구나.

public enum Elvis {
  INSTANCE;
  …
}

이 방법은 기능적으로는 public filed 접근 방법과 동일하지만, 간결하고, 여러 객체를 생성할 여지도 없으며, 직렬화도 제공한다는 점에서 차이가 있다.

a single-element enum type is the best way to implement a singleton

저자가 이 정도로 권장할 정도니까.. 사용해 봐야겠다.

2 thoughts on “EJ2E Item 3. 싱글톤 속성은 private 성성자 또는 enum 타입으로”

  1. “a privileged client can invoke the private constructor reflectively
    (Item 53) with the aid of the AccessibleObject.setAccessible method”

    이 부분은 java.lang.reflect.Constructor 클래스도 java.lang.reflect.AccessibleObject의 하위 클래스이니 setAccessible(true) 해 놓고 Reflection을 사용하면 private 생성자라도 외부에서 호출할 수 있기 때문에 쓴 말 같은데요, 사실 그렇게 까지 private 생성자를 호출해서 얻는 이득(?)이 있다거나, 특정 클래스를 남용할 수 있는 사례는 잘 생각나지는 않네요.

    전 예전에 테스트 coverage를 한 번 100% 만들어보고 싶어서 reflection으로 private 생성자를 호출했었는데, 그래도 100%는 안 떴었던 기억이 있기는해요 ;

    1. 음.. 그렇군요. 그렇게 해서 객체를 만들면 객체가 두 개 이상이 될 수 있다는 문제로군요. 우왕..

      감사합니다. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *