싱글톤 패턴 (Singleton Pattern)
싱글톤 패턴
하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴으로 보통 데이터베이스 연결 모듈에 사용한다.
하나의 인스턴스를 다른 모듈들이 공유하며 사용해 생성 비용이 줄어들지만 의존성이 높아지는 단점이 있다.
단점
Test Driven Development를 할 때는 단위 테스트를 진행하고 테스트가 서로 독립적이어야 하는데 싱글톤 패턴에서는 테스트들이 독립적인 인스턴스를 가지기 힘들다.
또한 모듈 간 결합도가 강해져 의존성이 증가하는데 이 문제는 의존성 주입을 통해 모듈 간의 결합을 느슨하게 만들 수 있다. 메인 모듈이 직접적으로 의존성을 부여하지 않고 중간에 의존성 주입자를 거쳐 하위 모듈에 의존성을 부여함으로써 의존성을 보다 떨어뜨린다. 의존성 주입을 사용할 시 모듈을 쉽게 교체할 수 있는 구조가 되고 의존성 방향이 일관되진다. 하지만 모듈이 보다 분리되어 복잡성이 증가할 수 있는 단점은 존재한다.
의존성 주입 시에는 원칙을 지켜주며 만들어야 한다.
" 상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않고 둘다 추상화에 의존하며 추상화는 세부사항에 의존하지 않는다.
구현 형태
늦은 초기화 싱글톤 패턴
멀티 스레드 환경에 취약하다. 스레드 A와 B가 있다고 할 때 A가 인스턴스를 생성하려는 도중 제어권이 B에 넘어가게 되면 B도 인스턴스를 생성하려 하고 인스턴스가 두 번 생성되는 문제가 발생한다.
getInstance() 메소드에 synchronized를 추가하여 스레드 동시 접근 문제를 해결할 수 있지만 인스턴스 리턴 시 마다 동기화를 진행하기 때문에 성능 저하가 생길 수 있다.
이른 초기화 싱글톤 패턴
getInstance()가 호출되는 시점이 아닌 class가 시작되는 순간 인스턴스가 생성되기 때문에 무조건 하나의 인스턴스만 생성되게 할 수 있다. 하지만 인스턴스를 사용하지 않는다면 미리 만들어 놓은 인스턴스로 인해 메모리 낭비가 생길 수 있다.
Double Checked Locking 싱글톤 패턴
동기화를 getInstance() 내부에서 처리하고 인스턴스가 이미 존재할 시 동기화를 진행하지 않기 때문에 성능 저하를 막을 수 있으며 인스턴스를 필요할 때 만들어 줄 수 있다.
Lazy Holder 싱글톤 패턴 (**)
getInstance() 호출 시에 인스턴스를 static으로 생성해 한 번만 생성하도록 하고
final을 추가하여 인스턴스 값이 변동되지 않도록 한다.