Programs/Java

객체의 생성과 소멸 - 3. private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자.

outliers 2012. 10. 30. 11:30

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) 상황에서도 직렬화가 자동으로 지원되고, 인스턴스기 여러 개 생기지 않도록 확실하게 보장해 준다. 싱글톤을 구현하는 가장 좋은 방법이다.