함수와 같은 무상태 객체나 설계상 유일해야 하는 컴포넌트처럼 인스턴스를 오직 하나만 생성할 수 있는(생성해야만 하는) 클래스를 싱글톤 객체라고 한다.
자세한 싱글톤 클래스를 구현하는 방법은 이곳을 참조하기 바란다.
클래스를 싱글톤으로 작성했을 경우의 문제점은 무엇인가 생각해보자. SOLID 원칙에서의 개방-폐쇄 원칙(OCP)는 변하는 것과 변하지 않는 것을 구분하고 그 두 모듈이 만나는 지점에 인터페이스를 작성하고 변하지 않는 모듈이 인터페이스에만 의존하도록하여 자기 자신은 변경하지 않고 기능을 확장할 수 있도록 해야한다는 원칙이다. 인터페이스에 의존하지 않고 구체 클래스 에 의존하게 되어버리면 OCP 원칙에 위배된다. 더욱이 그 구체 클래스가 싱글톤 클래스라면 생성자의 접근 제어자를 private으로 선언했을테니 상속을 통해 테스트 전용 클래스를 주입할 수도 없게된다. A라는 클래스가 싱글톤 클래스에 의존하고 있고, 그 싱글톤 클래스가 다른 서버와 통신을 한다거나 DB에서 조회를 하는 로직이 포함되어 있다고 가정하자. A클래스가 의존하는 싱글톤 객체를 교체할 수 없기 때문에 A 클래스를 테스트 할때마다 테스트 대상이 아닌 싱글톤 인스턴스의 로직이 수행될 것이다.
대표적인 싱글톤 클래스를 구현하는 방법은 public static final 필드를 사용하거나 getInstance와 같은 정적 팩토리 메소드를 제공하는 것이다.
public static final 필드를 사용하여 클래스가 로딩될 때 초기화하는 방법
이 방식은 Singleton 클래스가 싱글톤이라는 것임이 명확하게 드러나있다. public static final로 선언되어 있으니 절대로 다른 객체를 참조할 수 없고 생성자가 private으로 선언되어 있으니 외부에서 new 연산자를 사용해서 Sigleton클래스를 생성할 수 없다.
public class Sigleton{
public static final Sigleton INSTANCE = new Sigleton();
private Sigleton() {}
}
정적 팩토리 메소드를 통해 싱글톤 인스턴스를 반환하는 방법
정적 팩토리 메소드를 통해 싱글톤 인스턴스를 반환하는 방법의 장점은 getInstance라는 메소드 (API)를 바꾸지 않고도 인스턴스를 생성하는 방법을 바꿀 수 있다는 것이다. 지금은 싱글톤 방식으로 인스턴스를 생성하지만 메소드를 호출할 때마다 새로운 객체를 반환하도록 변경하기가 쉽다.
public class Sigleton{
private static final INSTANCE = new Sigleton();
private Sigleton(){}
public Sigleton getInstance(){return Sigleton;}
}