본문 바로가기
[기타]

싱글톤(Singleton)이란?

by PhoB 2023. 2. 7.

싱글톤 패턴(Singleton Pattern)

  • 디자인 패턴의 일종
  • 객체를 매번 생성하지않고 실행시점에 생성된 혹은 처음으로 생성된 객체만을 이용하는 것.
  • 즉 객체에대한 인스턴스가 단 한개만 존재한다.
  • 이후에 호출된 생성자는 최초에 만들어진 객체를 리턴한다.

주로 사용되는 곳

  • DBCP(DataBase Connection Poll)
  • 안드로이드 앱
  • 캐시 등등...

 

싱글톤 패턴의 장점

  1. 메모리
    • 인스턴스가 단 한개이기 때문에 new 키워드를 이용하여 매번 객체를 생성하는것보다 메모리 측면에서 우수하다.
  2. 속도
    • 미리 생성된 인스턴스를 활용하기 때문에 속도측면에서도 이점이 있다.
  3. 데이터 공유
    • 전역 인스턴스이기 때문에 타 클래스에서 사용도 용이하다. 즉 데이터 공유하기 좋다.

 

싱글톤 패턴의 단점

  1. 클래스간 의존성 심화
    • 만들어진 객체를 다른 클래스에서 자주 공유할 경우 클래스 끼리의 의존도가 높아지게된다.
    • 이 경우 객체지향원칙에 어긋나게 된다.
  2. 테스트의 어려움
    • 엮여있는곳이 많은 싱글톤 패턴은 특정기능의 테스트를 진행하는데 어려움이있어 매번 테스트를 할 때마다 인스턴스를 초기화해줘야한다는 문제가 있다.
  3. 멀티스레드 환경에서의 문제
    • 싱글톤 패턴에서는 객체의 인스턴스가 한개만 생성되어야 하는데 멀티스레드 환경에서 인스턴스가 2개 이상 생성되는 경우가 발생할 수 있다.(동시성 문제)
    • 이 문제를 해결하기위해 각 언어별로 다양한 솔루션이 있다.
      • 자바의 경우
      • synchronized , Lazy Holder등 몇가지 방법이 있다. 다만 synchronized키워드는 특유의 성능저하가 발생하기때문에 권장하지 않는다.

 

싱글톤 패턴 코드 예시

1. 기초적인 싱글톤 패턴 구현 코드

public class SingletonExample {

	private static SingletonExample se  = null;
	private SingletonExample() {
		//생성자를 외부에서 호출하지 못하게 하기위해서 private타입으로 선언
	}
    
	public static SingletonExample getInstance() {
		if(se == null) {
			se = new SingletonExample();
		}
		return se;
	}
}

 

2. 인스턴스를 원할때 생성하는것이 아닌 처음부터 생성하는 방법

public class SingletonExample {

	private static SingletonExample se = new SingletonExample();
	//처음부터 인스턴스를 선언 ---> 이러면 불필요한 시스템 리소스를 낭비
	
	private SingletonExample() {
		//생성자를 외부에서 호출하지 못하게 하기위해서 private타입으로 선언
	}
	public static SingletonExample getInstance() {
		return se;
	}
}

이럴경우 인스턴스를 생성이 필요없을때도 생성하기 때문에 불필요한 리소스가 낭비된다(권장X)

 

 

3. synchronized키워드를 이용하는 방법

public class SingletonExample {
	private static SingletonExample se  = null;
	private SingletonExample() {}
	public synchronized static SingletonExample getInstance() {
		if(se ==null) {
			se = new SingletonExample();
		}
		return se;
	}
}

안전한 방법이지만 성능저하가 심하게 일어나 권장되지않는 방법이다.

Lazy initialization 부르기도 한다. Double Check locking이라는 방법을 통해 성능저하를 막아주는 방법이 있긴하지만 역시 권장되지 않는다.

 

 

4. LazyHolder 방식

public class SingletonExample {

	private SingletonExample() {}

	public static SingletonExample getInstance() {
		return LazyHolder.INSTANCE;
	}
	
	private static class LazyHolder {
 		public static final SingletonExample INSTANCE = new SingletonExample();
    }

}

가장 권장되고있는 방법으 LazyHolder.INSTANCE가 리턴되는 순간 클래스가 로딩되어 초기화가 진행되고 이 시점에 안정성을 보장한다

static을 통해 한번만 호출되도록하며 final을 통해 값이 다시 할당되는것을 막았다.

'[기타]' 카테고리의 다른 글

[JAVA]자바 환경 변수 설정 방법  (0) 2023.02.06