[Java]싱글턴 패턴(Singleton pattern)

싱글턴 패턴

자바로 개발을 할 때, 특정 클래스가 다수의 인스턴스로 여러 번 생성된다면, 문제가 될 수 있다. 자바에선 이를 디자인 패턴 중 하나인 싱글턴 패턴(Singleton pattern) 으로 방지한다.

싱글턴 패턴의 사용

커넥션 풀, 스레드 풀과 같은 자원을 사용해야 하는 클래스들이 인스턴스를 여러 번 만들면, 자원의 낭비가 되고, 예상할 수 없는 오류가 발생할 수 있다.
싱글턴 패턴을 적용한 클래스에는, 생성자에 제약을 걸어서 필요한 객체를 하나만 만들도록 하는 디자인 패턴이다.

싱글턴 패턴의 규칙

싱글턴 패턴의 클래스를 만들기 위해서는 다음의 규칙이 있어야 한다.

  • 생성자의 접근제어자를 private로 하여 외부에서 생성하지 못하도록 한다.

  • 하나만 존재하는 인스턴스를 반환할 수 있는 정적 메서드를 만들어야 한다.

  • 하나만 존재하는 인스턴스를 참조할 수 있는 정적 참조 변수를 만들어야 한다.

싱글턴 패턴을 적용한 클래스

데이터 베이스와 연결하는 가상의 클래스 SingletonEx가 있다고 하자.

public class SingletonEx {
	private SingletonEx() {};
	// 1번 규칙

	static SingletonEx SingletonExInstance;
	// 2번 규칙

	public static SingletonEx getInstance() {
	// 3번 규칙
		if(SingletonExInstance == null) {
			SingletonExInstance = new SingletonEx();
		}
		return SingletonExInstance;
	}

}

앞서 서술한 세 가지 규칙에 대한 싱글턴 패턴의 클래스이다.
규칙에 따라 내부 코드를 하나하나 살펴보자.

  private SingletonEx() {};
  // 1번 규칙

생성자의 접근제어자를 private로 하여 외부에서 인스턴스를 생성할 수 없도록 막아놨다.

  static SingletonEx SingletonExInstance;
  // 2번 규칙

전역으로 유일하게 인스턴스를 참조할 수 있는 참조 변수이기 때문에 정적으로 선언했다.

	public static SingletonEx getInstance() {
	// 3번 규칙
		if(SingletonExInstance == null) {
			SingletonExInstance = new SingletonEx();
		}
		return SingletonExInstance;
	}

정적 참조 변수를 반환할 정적 메서드이다.
if문을 설명하자면, 최초로 메서드를 호출했을 땐 당연히 싱글턴 패턴의 인스턴스도 없을 것이기 때문에,
SingletonExInstance이 null인지?로 그 유무를 판단하고 인스턴스가 없다면, private한 생성자를 통해 인스턴스를 만들어준다.
유일한 인스턴스가 존재하는 상태라면 정적 참조 변수를 return으로 반환한다.

Test 코드

public class SingletonTest {

	public static void main(String[] args) {
		//SingletonEx exam1 = new SingletonEx();
		//The constructor SingletonEx() is not visible

		SingletonEx exam2 = SingletonEx.getInstance();
		SingletonEx exam3 = SingletonEx.getInstance();
		SingletonEx exam4 = SingletonEx.getInstance();

		System.out.println(exam2);
		System.out.println(exam3);
		System.out.println(exam4);
	}

}


		//SingletonEx exam1 = new SingletonEx();
		//The constructor SingletonEx() is not visible

SingletonEx exam1 = new SingletonEx(); 라는 코드는,
The constructor SingletonEx() is not visible 라고 나온다.
싱글턴 패턴 적용을 위해 생성자를 private으로 막아두었기 때문이다.

		SingletonEx exam2 = SingletonEx.getInstance();
		SingletonEx exam3 = SingletonEx.getInstance();
		SingletonEx exam4 = SingletonEx.getInstance();

		System.out.println(exam2);
		System.out.println(exam3);
		System.out.println(exam4);

getInstance() 는 정적 메서드임으로, 클래스명.getInstance()로 호출하였고,
System.out.println(...) 에 대한 결과는 모두 동일한 클래스의 해쉬 코드값이 나오는 걸 알 수 있다.

주의사항

싱글턴 패턴으로 만들어진 단일 객체는 전역에서 공유할 수 있는 변수이기 때문에, 속성을 갖지 않는 것이 좋다.
하지만 읽기 전용으로 속성을 갖는 것은 문제가 되지 않는다.