2022. 3. 10. 14:14ㆍJava/Effective Java
Singleton
- 싱글톤 패턴은 인스턴스화를 제한하고, 클래스의 하나의 인스턴스만 JVM에 존재하도록 한다.
- 싱글톤 패턴은 Global access point에서 인스턴스를 가져올 수 있도록 제공한다.
- 로깅, 드라이버 개체, 캐싱 및 스레드 풀에 사용된다.
- Abstract Factory, Builder, Protorype and Facade 등과 같은 디자인 패턴에도 사용된다.
장점
- 객체를 생성하면 재사용이 가능해서 메모리 사용 낭비를 막을 수 있다.
- 전역 객체이기 때문에 다른 객체와도 공유가 가능하다.
단점
- 클래스의 싱글턴화 시 클라이언트 테스트가 어려워진다.
- 타입을 인스턴스 정의 시 구현한 인터페이스로 만든 싱글턴이 아닐시 인스턴스를 Mock로 대체 불가
싱글턴 생성 방식
- Public Static Final Method
- Static Factory Method
- Enum Type Method
어떻게 만드는 것일까?
Public Static Final Method
public class Computer{
public static final Computer INSTANCE = new Computer();
private Computer(){ - }
public void turnOff(){ - }
}
Public 이나 Protected 생성자가 없으면 Computer 클래스는 전체에서 단 '하나'의 인스턴스를 가지고 있다.
예외가 있다. Reflection API인 AccessibleObject.setAccessible을 사용해 Private 생성자 호출이 가능하다.
-> 두 번째 객체를 생성할 당시에 예외 호출을 사용하면 된다.
Reflection API -> 클래스의 구체적인 타입을 얻지 못해도 클래스의 정보에 대해 접근이 가능하다.
장점
- 싱글턴임이 API에 명확히 표시한다.
- 간결적이다.
Static Factory Method
public class Computer{
public static final Computer INSTANCE = new Computer();
private Computer(){ - }
public static Computer getInstance(){
return INSTANCE;
}
public void turnOff(){ - }
}
getInstance() 메소드에 모든 호출을 동일한 객체로 참조 변환 Public이나 Protected 생성자가 없기에 다른 인스턴스는 생성 할 수 없다.
INSTANCE 초기화를 위해 Private은 단 '한 번'만 호출한다.
장점
- API 변경 할 필요가 없다.
- 싱글턴이 아니게 변경 할 수 있다.
- thread 별로 다른 인스턴스 넘겨주기가 가능하다.
- Static을 Static Generic Singleton으로 만들 수 있다.
- Static Method의 참조를 Supplier로 사용하는 식이다.
- Computer:: getInstance -> Supplier
Supplier Interface -> 무언가로 반환하는 함수형 인터페이스 -> Lazy Initialization
앞서 두 방식으로 생성된 싱글턴을 직렬화시 단순히 Serializable을 선언하는 것으로 실행되지 않는다.
-> 모든 Instance 필들를 transient 선언하고 readResolve 메소드 제공해야 한다.
이렇게 하지 않으면 새 인스턴스가 생성되고 -> 가짜 Computer가 생성된다.
private Object readResolve(){
return INSTANCE;
}
Enum Type
public enum Computer{
INSTANCE;
public void turnOff(){ - }
}
1번과 비슷하게 더 간결하고, 노력 없이도 직렬화가 가능하다. Enum 방식은 어떤 상황에서도 제 2의 인스턴스가 생성되는 것을 막아준다.
그래도 대부분 enum 방식으로 싱글턴 생성해주는 것이 가장 좋다.
단, 만들려고 하는 싱글턴이 Enum의 클래스를 상속하면 이 방법은 사용 할 수 없다.
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 아이템 5 : 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2022.03.15 |
---|---|
[Effective Java] 아이템 4 : 인스턴스화를 막으려거든 Private 생성자를 사용해라 (0) | 2022.03.14 |
[Effective Java] 아이템 2 : 생성자에 매개변수가 많다면 빌더를 고려하라 (2) | 2022.03.08 |
[Effective Java] 아이템 1 : 생성자 대신 정적 팩토리 메소드를 고려하라 (0) | 2022.03.01 |
[Effective Java] 이펙티브 자바를 읽기 시작.. (1) | 2022.02.28 |