싱글톤 패턴(Singleton Pattern)
- 디자인 패턴의 일종
- 객체를 매번 생성하지않고 실행시점에 생성된 혹은 처음으로 생성된 객체만을 이용하는 것.
- 즉 객체에대한 인스턴스가 단 한개만 존재한다.
- 이후에 호출된 생성자는 최초에 만들어진 객체를 리턴한다.
주로 사용되는 곳
- DBCP(DataBase Connection Poll)
- 안드로이드 앱
- 캐시 등등...
싱글톤 패턴의 장점
- 메모리
- 인스턴스가 단 한개이기 때문에 new 키워드를 이용하여 매번 객체를 생성하는것보다 메모리 측면에서 우수하다.
- 속도
- 미리 생성된 인스턴스를 활용하기 때문에 속도측면에서도 이점이 있다.
- 데이터 공유
- 전역 인스턴스이기 때문에 타 클래스에서 사용도 용이하다. 즉 데이터 공유하기 좋다.
싱글톤 패턴의 단점
- 클래스간 의존성 심화
- 만들어진 객체를 다른 클래스에서 자주 공유할 경우 클래스 끼리의 의존도가 높아지게된다.
- 이 경우 객체지향원칙에 어긋나게 된다.
- 테스트의 어려움
- 엮여있는곳이 많은 싱글톤 패턴은 특정기능의 테스트를 진행하는데 어려움이있어 매번 테스트를 할 때마다 인스턴스를 초기화해줘야한다는 문제가 있다.
- 멀티스레드 환경에서의 문제
- 싱글톤 패턴에서는 객체의 인스턴스가 한개만 생성되어야 하는데 멀티스레드 환경에서 인스턴스가 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 |
---|