Effective Java 3 [Item 3] - Private 생성자나 열거 타입으로 싱글턴임을 보증하라

mhyun, Park·2022년 3월 21일
0
post-thumbnail
post-custom-banner

싱글턴(Singleton)이란?

싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다. 즉, 객체나 설계상 유일해야 하는 시스템 컴포넌트이다.
싱글턴은 인스턴스를 mock으로 대체할 수 없기 때문에 테스트에 어려움이 있을 수 있다.

싱글턴을 만드는 방식은, 보통 아래 두 방법 중 하나다.

싱글턴(Singleton)을 만드는 방법

(1) public static final 필드 방식의 싱글턴

  • private 생성자는 Elvis.INSTANCE를 초기화할 때 딱 한 번만 호출된다.
  • public이나 protected 생성자가 없으므로 Evlis 클래스가 초기화될 때 만들어진 인스턴스가 전체에서 하나뿐임이 보장된다.
    --> 하지만, Reflection API AccessibleObject.setAccessible을 사용해 private 생성자를 호출 할 수 있다.
    --> 생성자를 수정하여 두 번째 객체가 생성되려 할 때 예외를 던지면 된다.
public class Elvis{
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() {...}
    
    public void leaveTheBuilding() {...}
}

(2) static factory 방식의 싱글턴

  • Elvis.getInstance()는 항상 같은 객체의 참조를 반환하므로 딱 하나의 Instace는 보장된다.
  • Reflection API 예외는 (1)과 똑같이 적용 된다.
public class Elvis{
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() {...}
    
    public static Elvis getInstance() { retrun INSTANCE; }
    
    public void leaveTheBuilding() {...}
}

[장점]

  1. API를 바꾸지 않고도 싱글턴이 아니게 변경할 수 있다.
public static Elvis getInstance() { retrun new Elvis(); }
  1. static factory를 generic singleton factory로 만들 수 있다.
// 제네릭으로 타입설정 가능한 인스턴스를 만들어두고, 
// 반환 시에 제네릭으로 받은 타입을 이용해 타입을 결정한다.
public class GenericFactoryMethod { 
	public static final Set EMPTY_SET = new HashSet(); 
	
    public static final <T> Set<T> emptySet() { 
		return (Set<T>) EMPTY_SET; 
	} 
}

출처: https://jake-seo-dev.tistory.com/13 [제이크서 블로그]
  1. 정적 팩토리의 메소드 참조를 Supplier로 사용할 수 있다.
Elvis::getInstaceSupplier<Evlis> 로 사용한다.

(3) 원소가 하나인 Enum을 선언한다.

  • Enum 이기에, Enum 외의 클래스를 상속해야 한다면 해당 방법은 사용할 수 없다.
public enum Elvis{
	// 인스턴스는 하나만 만들 수 있음
	INSTANCE; 

	public String getName() {
		return "아무개";
	}
}

String name = Elvis.INSTANCE.getName();
profile
Android Framework Developer
post-custom-banner

0개의 댓글