객체의 생성과 소멸 - 3. private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자.
Effect Java 제2판(Joshua Bloch / Addison Wesley) 을 공부하고 정리한 내용 입니다.
3. private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자.
싱글톤(singleton)은 정확히 하나의 인스턴스만 생성되는 클래스이다.
자바 1.5 버전 이전에는 싱글톤을 구현하는 방법이 두 가지 있었으며, 두 방법 모두 생성자를 private으로 하고, 유일한 인스턴스에 접근할 수 있도록 public static 멤버를 외부에 제공한다.
1. public final 필드를 갖는 싱글톤
// public final 필드를 갖는 싱글톤 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leaveTheBuilding() { ... } }
public이나 protected 생성자가 없으므로 private 생성자는 딱 한번만 호출되어 public static final 필드인 Elvis.INSTANCE를 초기화 한다. 클래스가 최초 한 번 초기화 될 때 정확히 하나의 인스턴스만 생길 것이다.
2. static 팩토리 메소드를 갖는 싱글톤
// static 팩토리 메소드를 갖는 싱글톤 public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTANCE; } public void leaveTheBuilding() { ... } }
1번 방법의 주된 장점은, 멤버 필드만 봐도 싱글톤 클래스인지 명쾌하게 알 수 있다는 것이다. 즉 public static 필드가 final 이므로 그 필드는 항상 같은 객체 참조를 갖는다.
2번 방법의 장점은, 클래스의 API를 변경하지 않고 클래스에서 반환하는 싱글톤 인스턴스의 형태를 바꿀 수 있는 유연성을 제공한다는 것이다. 예를 들어, 팩토리 메소드에서는 오직 하나의 인스턴스를 반환하지만, 이 메소드를 호출하는 각 스레드(thread)마다 하나씩의 인스턴스를 반환하도록 쉽게 수정할 수 있다.
1, 2번의 방법은 직렬화 하는데 불편함이 있다.
3. 자바 1.5 이후 버전에서는 싱글톤을 구현하는 다른 방법이 있다. 하나의 요소를 갖는 열거형 타입(enum)을 만들면 된다.
// 열거형 (Enum) 싱글톤 - 가장 좋은 방법임. public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
이 방법은 public 필드 방법과 기능적으로 동일하지만 더 간단하다. 그리고 복잡한 직렬화나 리플렉션(reflection) 상황에서도 직렬화가 자동으로 지원되고, 인스턴스기 여러 개 생기지 않도록 확실하게 보장해 준다. 싱글톤을 구현하는 가장 좋은 방법이다.