싱글턴 패턴이란 인스턴스를 하나만 만들어 사용하기 위한 패턴이다.
커넥션 풀, 스레드 풀, 디바이스 설정 객체 등 인스턴스를 여러 개 만들면 불필요한 자원을 사용해 프로그램이 예상치 못한 결과를 낳을 수 있다. 따라서 싱글턴 패턴은 오직 인스턴스를 하나만 만들고 그것을 계속해서 재사용한다.
싱글턴 패턴을 구현하려면 객체 생성을 위한 new
에 제약을 걸어야 하고, 만들어진 단일 객체를 반환할 수 있는 메서드가 필요하다.
new
를 실행할 수 없도록 생성자에 private
접근 제어자를 지정한다.public class Singleton {
static Singleton singletonObject;
// 단일 객체를 저장하기 위한 정적 참조 변수
private Singleton() {} // private 생성자
// 단일 객체 반환 정적 메서드
public static Singleton getInstance(){
if(singletonObject == null){
singletonObject = new Singleton();
}
return singletonObject;
}
}
public class Client {
public static void main(String[] args) {
// private 생성자이므로 new를 통해 인스턴스를 생성할 수 없다.
// Singleton s = new Singleton();
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
s1 = null;
s2 = null;
s3 = null;
}
}
✔️ 클래스가 하나의 인스턴스만 갖는다는 것을 확신할 수 있다.
✔️ 인스턴스에 대한 전역 접근 지점을 얻는다.
✔️ 싱글턴 객체는 처음 요청될 때만 초기화 된다.
❌ 단일 책임 원칙을 위반한다. 싱글턴은 한 번에 두 가지 문제를 동시에 해결한다.
❌ 싱글턴 패턴은 잘못 설계된 디자인을 가릴 수 있다.
❌ 다중 스레드 환경에서 여러 스레드가 싱글턴 객체를 여러 번 생성하지 않도록 하기 위한 처리가 필요하다.
❌ 싱글턴 클라이언트 코드를 유닛 테스트하기 어려울 수 있다. 많은 테스트 프레임워크들은 모의 객체들을 생성할 때 상속에 의존하기 때문이다. 싱글턴 클래스 생성자는 비공개이고 대부분 언어에서 정적 메서드를 오버라이딩하는 것이 불가능 해 싱글턴의 한계를 극복할 수 있는 방법을 생각해야 한다. 결국 테스트를 작성하지 않거나 싱글턴 패턴을 사용하지 않아야 한다.
디자인 패턴에 뛰어들기
스프링 입문을 위한 객체지향의 원리와 이해