Serialization
싱글턴 클래스를 직렬화하려면 Serializable을 구현한다고 선언하는 것만으로는 부족하다.
- 모든 인스턴스 필드를 일시적 (transient)라고 선언하고
- readResolve 메서드를 제공해야 한다.
이렇게 하지 않으면 직렬화된 인스턴스를 역직렬화할 때마다 새로운 인스턴스가 생성된다.
Reflection 공격
- 권한이 있는 사용자는
AccessibleObject.
setAccesible
을 사용해 private 생성자를 호출할 수 있음
- 생성자를 수정해서 두번 째 객체가 생성되려 할 때 예외를 던지게 하여 방어 할 수 있음
Protected constructor
간단히 싱글톤으로 만들려면 private 생성자를 쓰면된다.
근데 private 생성자만 쓰면 상속을 할 수 없다. 그렇다고 public을 쓰면 싱글톤을 보장 할 수 없다.
그래서 절충안으로 protected 생성자를 쓰게되면 한가지 단점이 있다.
- 같은 패키지에서 생성자 호출 가능 → 싱글톤 만을위한 패키지를 만들어 해결 가능
Class Loader
서버에서 클래스 로더를 어떻게 구성하느냐에 따라 싱글톤 클래스임에도 불구하고 1개 이상의 객체가 만들어질 수 있다. 따라서 Java 언어를 이용한 싱글톤 기법은 서버 환경에서 싱글톤이 꼭 보장된다고 볼 수 없다. 또한 여러 개의 JVM에 분산돼서 설치되는 경우에도 독립적으로 객체가 생성된다.
Stateless
- 특정 클라이언트에 의존적인 필드가 있으면 안된다.
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다!
- 가급적 읽기만 가능해야 한다.
- 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
Anti-Pattern?
- 클라이언트가 구체 클래스에 의존하게 함→ DIP 위반
- 테스트하기 어려움
- Mock을 생성할 수 없음
- many test frameworks rely on inheritance when producing mock objects
- you will need to think of a creative way to mock the singleton
- 보통 static initializer를 통해 객체가 생성된는 순간을 보장할 수 없음
- 또한 Clinet와의 강한 결합도
- → 유연성이 떨어짐