싱글톤
정의
정확히 하나의 인스턴스만 생성하는 클래스로 시스템상에 유일하게 존재하는 컴포넌트를 의미한다.
구현 방법
Java 1.5 이전
전제 조건
- 생성자를 private로 선언한다.
- public static으로 유일한 인스턴스를 만들어 외부에서 접근할 수 있게 한다.
방법1. 멤버를 final 필드로 하기
public static class Doorlock {
public static final Doorlock INSTANCE = new Doorlock();
private Doorlock() {}
public void unlock() {}
}
- 코드의 1. : 생성자는 딱 한번 호출되어 인스턴스 초기화에 사용된다.
- 다른 생성자는 없기때문에 하나의 도어락이 생김을 보장한다.
이 인스턴스를 사용하게 되면 변경할 방법이 없고 객체 하나만 사용하는 것임을 알 수 있다.
- 멤버 필드만으로 싱글톤 클래스를 명확하게 알 수 있다.
- public static final이므로 항상 동일한 인스턴스를 참조한다.
- 클라이언트에서 사용하지 않아도 인스턴스가 항상 생성되어 메모리가 낭비된다.
방법2.
public static class Doorlock {
private static final Doorlock INSTANCE = new Doorlock();
public static Doorlock getInstance(){
return INSTANCE;
}
private Doorlock() {}
public void unlock() {}
}
- 인스턴스를 생성하는 곳이 유일하고, 그 곳을 참조해서 반환하기 때문에 둘 이상의 인스턴스는 절대 생성되지 않는다.
- 클래스의 API를 변경하지 않고 클래스에서 반환하는 싱글톤 인스턴스의 형태를 유연하게 바꿀 수 있다.
- 팩토리 메소드에서는 유일한 인스턴스를 반환하지만, 이 메서드를 호출하는 각 스레드는 하나씩 인스턴스를 반환하도록 쉽게 수정할 수 있다.
- 제너릭 타입으로 사용할 수도 있다.
- 정적 팩터리의 메서드 참조를 공급자(supplier)로 사용할 수 있다.
방법 1, 2의 직렬화
- 클래스 선언부에 implements Serializable 추가
- 모든 인스턴스 필드를 trasient로 선언
- 역직렬화시 새로운 인스턴스 생성을 막기위해 readResolve 메서드를 추가.
Java 1.5 이후
열거형(enum) 타입 사용하기
public enum Doorlock {
INSTANCE;
public void unlock() {}
}
- 간결하다.
- 복잡한 직렬화나 reflection 상황에서 직렬화가 자동으로 지원되고 인스턴스가 여러 개 생기지 않도록 보장한다.
- 가장 추천.
참조
Effective Java