2장 객체 생성과 파괴 - 싱글턴

정지수 JisooJung·2021년 11월 21일
0

Effective Java 스터디

목록 보기
4/6
post-custom-banner

아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라

싱글턴(singleton) 클래스는 인스턴스를 오직 하나만 생성할 수 있는 클래스이다.
싱글턴 클래스는 private 생성자, 혹은 열거타입으로 보증할 수 있다.

private 생성자

public static final 필드 방식

public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    
    // final 필드인 Elvis.INSTANCE를 초기화할 때 단 한번 호출됨
    private Elvis() {...}
    
    public void leaveTheBuilding() {...}
}

위 코드의 Elvis클래스는 public , protected 생성자가 없으므로 싱글턴임이 보장된다.
단, 클라이언트는 AccessibleObject.setAccessble을 사용해 private생성자를 호출할 수 있다. 이는 아래와 같이 방어할 수 있다.

public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    
    // 두 번째 객체가 생성되려 할 때 예외를 던짐
    private Elvis() {
    	if(INSTANCE != null) {
        	throw new Exception("생성자를 호출할 수 없습니다.");
        }
        ...
    }
    
    public void leaveTheBuilding() {...}
}

장점1. public static 필드가 final 이므로 절대 다른 객체를 참조할 수 없다.
장점2. 간결하다.

정적 팩터리 방식

public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() {...}
    
    // 항상 같은 객체의 참조를 반환
    public static Elvis getInstance() { return INSTANCE; }
    
    public void leaveTheBuilding() {...}
}

장점 비교

public static final 필드정적 팩터리
public static필드가 final이므로 절대 다른 객체를 참조할 수 없다.
간결하다
API 수정 없이 싱글턴이 아니게 변경할 수 있다.
정적 팩터리를 제네릭 싱글턴 팩터리로 만들 수 있다.
팩터리의 메서드 참조를 공급자(supplier)로 사용할 수 있다. ex) Supplier<Elvis>

정적 팩터리의 장점이 굳이 필요하지 않다면 public 필드 방식이 좋다.

직렬화

싱글턴 클래스를 직렬화하려면 모든 인스턴스 필드를 일시적(transient)이라고 선언 readResolve 메서드를 제공해야 한다. (그렇지 않으면 역직렬화 시 새로운 인스턴스 생성됨)

// 싱글턴임을 보장해주는 readResolve 메서드
private Object readResolve() {
	// '진짜' Elvis를 반환하고, 가짜 Elvis는 가비지 컬렉터에 맡김
	return INSTANCE;
}

열거 타입 (바람직!)

public enum Elvis {
	INSTANCE;
    
    public void leaveTheBuilding() {...}
}

장점1 public 필드 방식과 비슷하나 더 간결함
장점2 직렬화 용이
장점3 복잡한 상황에서도 제 2의 인스턴스가 생기는 일을 완벽히 방어

원소가 하나뿐인 열거 타입이 싱글턴을 만드는 가장 좋은 방법이다.
(단, Enum 외 클래스 상속 시 사용 불가능하다.)


Reference

조슈아 블로크Joshua Bloch, 『이펙티브 자바 Effective Java 3/E』, 개앞맵시(이복연) 옮김, 인사이트(2018), p23-25.

profile
Study&Work&Log
post-custom-banner

0개의 댓글