back-end
effective-java-3
BE_규원
2025. 1. 1. 18:38
Item 3: Enforce the singleton property with a private constructor or an enum type
singleton 적용할 때,
생성자를 private 으로 막거나 enum type singleton 을 사용해야 한다.
singleton
- 인스턴스를 하나만 생성할 수 있는 클래스이다.
- singleton 은 mock 객체를 활용한 테스트 어렵다.
- mock 객체를 사용하려면 singleton 이 interface 를 구현해야 한다.
singleton 구현 방법 3가지
1. public final 필드를 사용하는 방법
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public void leaveTheBuilding() {
}
}
- 클래스의
public static final
필드로 싱글톤 인스턴스 제공한다. - 코드가 간결하다.
- API를 통해 싱글톤임이 명확하다.
- 리플렉션을 통한 무단 생성 공격이 가능하다.
- 이를 방지하려면 생성자에서 두번째 인스턴스 생성 시 예외를 던지게 해야 한다.
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
if( INSTANCE != null) {
throw new RuntimeException("Can't create Constructor");
}
}
}
2. 정적 팩토리 메서드
를 사용하는 방법
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public static Elvis getInstance() {
return INSTANCE;
}
public void leaveTheBuilding() {
}
}
- 싱글톤 인스턴스를 반환하는
public static
메서드이다. - 싱글톤 여부를 나중에 변경할 수 있다는 유연성을 제공한다.
- 메서드 참조 사용이 가능하다.
3. Enum
을 사용하는 방법 (권장)
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() {
}
}
- 싱글톤 인스턴스를 열거형의 요소로 선언한다.
- 코드가 간결하다.
- 직렬화와 리플렉션 공격에 강하다.
- 상속이 필요한 경우는 사용할 수 없다.
싱글톤 클래스에서 직렬화를 지원하려면 모든 필드를 transient로 선언하고 readResolve 메서드를 추가해야 한다.
그렇지 않으면 직렬화-역직렬화 과정에서 새로운 인스턴스가 생성될 수 있다.