일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Singleton
- Java
- 공부
- 후기
- 인강리뷰
- study
- 인코딩
- 이펙티브자바
- 에러
- 프로그래머스
- 회고
- 독서리뷰
- Head First Design Pattern
- javascript
- 자바
- 독서
- JPA
- math
- Eclipse
- 인프런
- 우아한테크코스
- 디자인패턴
- 알고리즘
- 매핑
- spring
- Design Pattern
- 람다
- 오라클
- 카카오톡1차
- Oracle
- Today
- Total
Lee's Grow up
[디자인패턴/Design Pattern] Singleton 패턴 / 싱글톤 패턴 본문
관련 내용은 [자바 언어로 배우는 디자인 패턴 입문]
이라는 책의 공부 내용을 개인적으로 정리한 내용입니다.
처음 배우는 부분이기 때문에 틀린 부분이 있다면 지적해주시면 감사하겠습니다.
또한 관련 내용은 Effective Java의 내용도 포함되어 있습니다.
1. Singleton 패턴이란?
생성자가 여러 차례 호출되어도 실제 생성되는 객체는 최초의 1개이고, 그 이후의 생성자는 최초 생성자를 통해 생성한 객체를 리턴하는 방식입니다. 즉, 인스턴스가 1개 밖에 존재하지 않는 것을 보증하는 패턴입니다.
2. Singleton 패턴의 등장 인물
이번 포스팅에서 사용될 요소들의 역할입니다.
- Singleton의 역할
- 유일한 인스턴스를 얻기 위한
static
메소드를 가지며. 이 메소드는 언제나 동일한 인스턴스를 반환하는 역할
- 유일한 인스턴스를 얻기 위한
Singleton 패턴의 클래스 다이어그램
3. 예제
이제 Singleton의 예제로 내용을 구체화 해보겠습니다. 다만 Singleton
방식에 대해서 책의 내용은 입문 책이라 그런지 가장 고전적인 방법을 안내해주고 있어서 추가로 내용을 정리해서 올립니다.
3-1. 이 책에서 소개하는 Singleton 패턴
가장 기본적인 singleton
패턴 방식이며, 아래 내용을 이해하기 위한 기본 구조입니다. 하지만 환경에 따라 여러 문제점이 발생하기 때문에 해결법은 아래에서 추가로 설명하겠습니다.
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
System.out.println("인스턴스를 생성했습니다.");
}
public static Singleton getInstance() {
return singleton;
}
}
문제점
위와 같은 방식으로 Singleton
을 정적 팩토리 방식으로 생성하면, 간결하다는 장점이 존재한니다.
하지만 Reflection
에 의해서 객체의 인스턴스는 단 1개만 보장한다는 방식이 파괴되며, 직렬화 과정에서 같은 객체라는 보장이 되지 않습니다. 아래 예시에서 Reflection
에 대한 예시를 설명하겠습니다. 직렬화에 대한 테스트는 독자분들에게 맡기겠습니다.
싱글톤 파괴
public class Main {
public static void main(String[] args) throws Exception {
StaticFactorySingleton singleton1 = StaticFactorySingleton.getInstance();
System.out.println(singleton1.hashCode());
Constructor cs = StaticFactorySingleton.class.getDeclaredConstructor();
cs.setAccessible(true);
StaticFactorySingleton singleton2 = (StaticFactorySingleton)cs.newInstance();
System.out.println(singleton3.hashCode());
}
}
위와 같이 실행을 하게 되면 일반적인 호출로는 같은 인스턴스를 반환해주지만, reflection
을 사용한 객체는 전혀 새로운 객체를 반환해줍니다.
실행 결과
인스턴스를 생성했습니다.
5433634
인스턴스를 생성했습니다.
2430287
3-2. EFFECTIVE Java에서 소개하는 방법
해당 방식전에 Singleton
을 보장( 멀티쓰레드, 직렬화 ) 하기 위한 방식으로 Double Checked Locking
방식이 존재하지만, 현재 사용하지 않는다고 해서 설명은 생략하지만 관련 글을 읽어보면 좋을거 같아서 링크를 남깁니다.
https://medium.com/@kevalpatel2106/how-to-make-the-perfect-singleton-de6b951dfdb0
그러면, 본론으로 들어와서 EFFECTIVE Java
에서 소개하는 방식을 소개하겠습니다.
내용은 간단합니다. singleton
을 사용할 객체를 class
가 아닌 enum
으로 정의하는 방식입니다. 코드는 아래와 같습니다.
public enum Singleton {
INSTANCE;
}
위와 같은 방식은 우선 간결하고, 추가의 노력 없이 직렬화가 가능하고, 심지어 멀티쓰레드에서도 안정적입니다. 또한 리플렉션으로 생성자에 접근하지도 못합니다.
하지만 만들려는 Singleton
이 Enum
외의 클래스를 상속해야 하거나, java 1.5
이하 버전이라든지의 상황에서는 사용이 불가능합니다. 또한 메모리에 대한 성능 이슈도 존재합니다.
3-3. Initialization-on-demand holder idiom 방식
enum
방식은 안드로이드 개발시에 문제가 발생할 수 있어서 해당 방식이 제일 많이 사용하는 방식입니다. 이 방식을 사용하면, 위 본문에 소개에서 생략한 Double Checked Locking
과 같은 방식에서 사용한 synchronized
도 필요없어서 성능이 뛰어나고, enum
방식처럼 Java 버전에 상관이 없습니다. 코드는 아래와 같습니다.
public class Singleton{
private Singleton() { }
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
해당 방식에 대한 설명은 간단히 하자면, 객체가 필요로 할때 초기화를 미뤄서, 불필요하게 메모리를 잡아먹지 않습니다.Singleton
클래스를 로드를 해도 LazyHolder
클래스의 변수가 없기 때문에 메모리에 할당받지 않습니다.
이는 자바 클래스로더 매커니즘을 이용한 방식으로, Singleton
의 getInstance()
메소드를 호출하는 순간 LazyHolder Class
가 로딩됩니다.
이 때 Class를 로딩하고, 초기화하는 시점에 JVM에 의해서 thread-safe
를 보장하기 때문에, 불필요한 키워드로 인한 성능저하가 없기 때문에 실무에서 가장 많이 사용하는 방식이라고 합니다.
그러나, 다른 방식과 마찬가지로 Reflection
을 통해 파괴가 가능합니다.
4.마치며
위와 같으 Singleton
을 만드는 방법은 다양하며, 각각 장단점이 존재하니 상황에 따라 필요한 방식으로 선택하면 될 것 같습니다.
5. 관련 패턴
아래 4개는 인스턴스가 1개인 경우가 많이 존재합니다.
Abstract Factory
패턴Builder
패턴Facade
패턴Prototype
패턴 link
'PROGRAMMING > 디자인패턴' 카테고리의 다른 글
[디자인패턴/Design Pattern] Strategy 패턴 / 전략 패턴 (0) | 2019.12.11 |
---|---|
[디자인패턴/Design Patter] Prototype 패턴 프로토타입 패턴 (0) | 2019.11.27 |
[디자인패턴/Design Pattern] Factory Method 패턴 / 팩토리 메소드 패턴 (0) | 2019.11.22 |
[디자인패턴/Design Pattern] Template Method 패턴 / 템플릿 메소드 패턴 (0) | 2019.11.21 |
[디자인패턴/Design Pattern] Adapter 패턴 / 어뎁터 패턴 / Wrapper 패턴 (0) | 2019.11.21 |