[Java] Singleton Pattern
Java에서 Singleton 패턴이란 ❔
싱글톤 패턴은 소프트웨어 디자인 패턴 중에 하나로, 하나의 객체만을 생성해 이후에 호출된 곳에서는 생성된 객체를 반환하여 프로그램 전반에서 하나의 인스턴스만을 사용하게 하는 디자인 패턴을 말한다.
public class Singleton {
// Instance
private static Singleton instance = new Singleton();
// private construct
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
위 코드는 싱글톤 패턴을 적용한 예제이다. 객체를 static
변수로 설정하여 인스턴스화하지 않고 접근 제한자를 private
으로 설정해 직접적인 접근을 불가능하게 한다. 또한, 기본 생성자를 private
을 사용하여 생성 불가하게 함으로써 getInstance
함수를 통해서만 인스턴스를 얻을 수 있다.
Singleton 패턴을 사용하는 이유
오직 하나의 인스턴스만을 사용하게 함으로써 어떤 이점이 있을까 ❔
- 한 번의 객체 생성으로 재사용이 가능하기 때문에 메모리 낭비를 방지할 수 있다.
- 싱글톤으로 생성된 객체는 전역성을 띄기 때문에 다른 객체 간에 공유가 쉽다.
Singleton 패턴의 문제점
- 싱글톤 객체를 사용하는 객체 간의 결합도가 높아진다
싱글톤은 프로그램 전체에서 하나의 객체만을 공통으로 사용하고 있기 때문에 싱글톤 객체를 사용하는 객체 간의 결합도가 높아져 SOLID 중 개방-폐쇄 원칙(Open-Closed Pricipal)에 어긋날 가능성이 있다. - 내부 상태를 변경하기 어렵다.
싱글톤 객체를 수정할 경우 이를 참조하고 있는 모든 값들이 변경되어야 하기 때문에 변경에 유연하게 대처할 수 없다. - 멀티스레드 환경에서 동기화 문제가 발생할 수 있다.
Singleton 패턴 구현 방법
static block
static block을 사용하여 클래스가 로딩될 때 한번만 실행하게 되는 특성을 사용한 방법
문제점: 인스턴스가 사용되는 시점이 아닌 클래스 로딩 시점에 실행이 된다.
public class Singleton {
// Instance
private static Singleton instance;
// private construct
private Singleton() {}
static {
try { instance = new Singleton();}
catch(Exception e) {
throw new RuntimeException("Create instace fail. error msg = " + e.getMessage());
}
}
public static Singleton getInstance() {
return instance;
}
}
lazy init
static block을 개선하여 클래스 로딩 시점이 아닌 인스턴스를 요청할 때 생성하는 방법
문제점: 멀티스레드 환경에 취약하다. 특정 스레드가 동시에 getInstance 함수를 호출할 경우 인스턴스가 중복 생성되는 문제가 발생한다.
public class Singleton {
// Instance
private static Singleton instance;
// private construct
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {instance = new Singleton();}
return instance;
}
}
thread safe + lazy
lazy init에서의 getInstance 함수에 synchronized 키워드를 붙여 동기화 문제를 해결한 방법
문제점: synchronized 키워드는 성능 저하를 발생한다.
public class Singleton {
// Instance
private static Singleton instance;
// private construct
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {instance = new Singleton();}
return instance;
}
}
Holder
JVM의 클래스 로더 메커니즘과 클래스의 로드 시점을 이용하여 내부 클래스를 통해 생성 시킴으로써 쓰레드 간의 동기화 문제를 해결한 방법
현재 java에서 싱글톤 생성에서 사용하는 대표적인 방법
public class Singleton {
// private construct
private Singleton() {}
/**
* static member class
* 내부클래스에서 static 변수를 선언해야하는 경우 static 내부 클래스를 선언해야만 한다.
* static 멤버, 특히 static 메서드에서 사용될 목적으로 선언
*/
private static class InnerSingleton {
// 클래스 로딩 시점에서 생성
private static final Singleton uniqueInstance = new Singleton();
}
public static Singleton getInstance() {
return InnerSingleton.instance;
}
}
Reference
https://elfinlas.github.io/2019/09/23/java-singleton/
https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/