# item3) private 생성자나 열거 타입으로 싱글톤임을 보증하라

## **싱글톤**

* 인스턴스를 오직 하나만 생성할 수 있는 클래스
* 함수와 같은 무상태 객체나 설계상 유일해야하는 시스템 컴포넌트 등이 해당된다.
* 인터페이스를 구현한 싱글톤이 아니라면 mock 구현으로 대체가 불가능해 클라이언트를 테스트하기 어려워질 수 있다.

## **싱글톤 생성 방법**

### 방식 1) 생성자를 private으로 두고, <mark style="background-color:green;">public static 멤버 변수로 인스턴스에 접근</mark> 할 수 있도록 하는 방식

* reflection API를 통해 private 생성자를 호출하는 경우가 발생할 수 있기 때문에, 이를 대비하여 생성자 내부에서 예외를 던지도록 해야 한다.
* 간결하고, 해당 클래스가 싱글톤임이 명백히 드러난다.

### 방식 2) 생성자를 private으로 두고, <mark style="background-color:green;">정적 팩토리 메서드를 public static 멤버 변수로</mark> 두어 인스턴스에 접근할 수 있도록 하는 방식

* 유일한 인스턴스를 반환하도록 할 수도 있고, 스레드별로 다른 인스턴스를 넘겨주게 할 수도 있다. (방식1 보다 유연)
* 제네릭 싱글톤 팩토리로 만들 수 있다.
* 정적 팩토리의 메서드 참조를 공급자로 사용 가능하다.

### 방식 3) 원소가 하나인 enum 클래스로 선언

간결하고, 직렬화 상황에서 가짜 인스턴스가 생성되지 않도록 막아준다.

싱글톤 클래스가 enum외의 클래스를 상속해야 하면 사용 불가

enum 타입이 다른 인터페이스를 구현하도록 선언은 가능

## **직렬화 문제**

* 방식 1\~2 로 생성된 싱글톤 클래스를 직렬화 할 때 모든 인스턴스를 transient로 선언하고, readResolve 메소드 제공해야 한다.
* 직렬화된 인스턴스를 역직렬화할 때마다 새로운 가짜 인스턴스가 생성되기 때문이다.

```java
private Object readResolve(){
	return INSTANCE;
}
```
