싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스다. 인스턴스를 하나만 만들어야 하는 예는 다음과 같다.
그러나 클래스를 싱글턴으로 만들면 테스트 하기가 어려워진다는 단점이 있다. 인터페이스를 구현해서 만든 싱글턴이 아니고서야 싱글턴 인스턴스를 가짜(mock)로 대체할 수 없기 때문이다.
그러면 싱글턴을 만드는 방식들은 무엇이 있는지 살펴보자.
// 코드 3-1 public static final 필드 방식의 싱글턴 (23쪽)
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {}
public void leaveTheBuilding() {}
}
private 생성자로 인스턴스화를 막고 public static final 필드를 통해 인스턴스를 얻을 수 있게 했다.
장점
단점
// 코드 3-2: 정적 팩터리 방식의 싱글턴
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() {}
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() {}
}
Elvis클래스의 getInstance() 메서드는 항상 같은 객체의 참조를 반환한다.
장점
단점
// 코드 3-3: 열거 타입의 싱글턴(바랍직한 방법, 25쪽)
public enum Elvis {
INSTANCE;
public void leaveBuilding() {}
}
객체의 수를 통제해야 할 때 열거 타입은 가장 바람직한 방법이다.
장점
단점
싱글턴 객체를 직렬화 하려면 Serializable을 구현하는 것 만으로는 부족하다. 역직렬화 할 때마다 새로운 인스턴스가 생성되기 때문이다. 싱글턴 객체를 올바르게 직렬화 하려면 모든 인스턴스 필드를 transient
으로 선언하고 readResolve()
메서드를 제공해야 한다.