소프트웨어 디자인 패턴에서 싱글턴 패턴을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.
객체의 인스턴스가 오직 1개만 생성되는 패턴
싱글톤 패턴의 핵심은 생성자를 private 접근 제한해서 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는 것이다.
private 클래스() {}
public class 클래스 {
// private 접근 권한을 갖는 정적 필드 선언과 초기화
private static 클래스 singleton = new 클래스(); // --①
// private 접근 권한을 갖는 생성자 선언
private 클래스() {}
// public 접근 권한을 갖는 정적 메소드 선언
public static 클래스 getInstance() { // --②
return singleton;
}
}
생성자를 호출할 수 없으므로 외부에서 마음대로 객체를 생성하는 것이 불가능해진다. 대신 싱글톤 패턴이 제공하는 정적 메소드를 통해 간접적으로 객체를 얻을 수 있다.
①에서는 자신의 타입으로 정적 필드를 선언하고 미리 객체를 생성해서 초기화시킨다. 그리고 private 접근 제한자를 붙여 외부에서 정적 필드값을 변경하지 못하도록 막는다.
②에서는 정적 필드값을 리턴하는 getInstance() 정적 메소드를 public으로 선언한다.
외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 것이다. getInstance() 메소드가 리턴하는 객체는 정적 필드가 참조하는 싱글톤 객체이다. 따라서 아래 코드에서 변수1과 변수2가 참조하는 객체는 동일한 객체가 된다.
클래스 변수1 = 클래스.getInstance();
클래스 변수2 = 클래스.getInstance();
1. 자원 공유 및 효율성: 싱글톤은 하나의 인스턴스만 생성되기 때문에 해당 클래스의 인스턴스를 여러 곳에서 공유하여 사용할 수 있다. 이는 메모리와 자원을 효율적으로 관리할 수 있게 해준다.
2. 전역 상태 관리: 싱글톤은 어플리케이션 내에서 전역적인 상태를 관리하는 데 유용하다. 다양한 부분에서 동일한 인스턴스를 참조하여 상태를 공유하거나 수정할 수 있다.
3. 인스턴스 생성 제어: 어떤 클래스가 항상 하나의 인스턴스만을 갖도록 강제함으로써, 해당 클래스에 대한 인스턴스 생성을 제어할 수 있다. 이를 통해 실수나 부적절한 생성을 방지할 수 있다.
4. 성능 개선: 인스턴스를 한 번만 생성하고 재사용하기 때문에, 반복적인 인스턴스 생성과 소멸에 따른 오버헤드를 피할 수 있다. 특히, 해당 클래스의 생성이 매우 비용이 크거나 시간이 오래 걸리는 경우에 성능 향상을 가져올 수 있다.
5. 전역 접근 지점: 어플리케이션 전반에 걸쳐 하나의 지점에서 인스턴스에 접근할 수 있기 때문에, 특정 객체에 대한 전역적인 접근 지점을 제공한다.
싱글톤은 전역 상태를 갖기 때문에 오용되면 코드의 복잡성을 증가시키고 테스트를 어렵게 만들 수 있다. 또한, 멀티스레딩 환경에서는 동기화 문제에 주의해야 한다.