티스토리 뷰
(Effective Java) 규칙3. private 생성자나 열거 타입으로 싱글턴임을 보증하라
싱글턴
- 싱글턴은 객체를 하나만 만들 수 있는 클래스
- 보통 유일할 수밖에 없는 시스템 컴포넌트 (window manager, file system)
- But, 클래스를 싱글턴으로 만들면 클라이언트를 테스트하기가 어려워짐
- 싱글턴이 어떠한 인터페이스의 구현체가 아니라면 가짜 구현이 어려움
싱글턴 구현 방법
-
싱글턴을 구현하는 방법 (JDK 1.5 이전)
-
public final 필드를 이용한 방법
//public final 필드를 이용한 싱글턴 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leaveTheBuilding() { ... } }
- 특징
- private 생성자는 public static final 필드인 Elvis.INSTANCE를 초기화 할때 한 번만 호출됨
- 주의할 점
- AccessibleObject.setAccessible 메서드의 도움을 받아 권한을 획득한 클라이언트는 리플렉션(reflection) 기능을 통해서 private 생성자를 호출할 수 있음
- 방지를 위해선 두번째 객체를 생성하라는 요청을 받으면 예외를 던지도록 수정해야 함
- https://stackoverflow.com/questions/4081227/singleton-pattern 참고
- AccessibleObject.setAccessible 메서드의 도움을 받아 권한을 획득한 클라이언트는 리플렉션(reflection) 기능을 통해서 private 생성자를 호출할 수 있음
- 특징
-
정적 팩토리를 이용하는 방법
//정적 팩터리를 이용한 싱글턴 패턴 public class Elvie { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance(){ return INSTANCE; } public void leaveTheBuilding() { ... } }
- 특징
- Elvis.getInstance는 항상 같은 객체에 대한 참조를 반환함 (물론 앞서 말한 공격은 여전히 가능함)
- public 필드를 사용하면 클래스가 싱글턴인지는 선언만 보면 금방 알 수 있어서 좋음
- 그러나, 최신 JVM에서는 정적 팩터리 메서드 호출을 항상 inline으로 처리하기 때문에 성능상 차이는 없음
- 장점
- API를 변경하지 않고도 싱글턴 패턴을 포기할 수 있다는 것임
- 스레드 마다 객체를 넘겨주도록 쉽게 수정이 가능
- 제네릭 타입을 수용하기 쉬움
- 그러나, 이런 장점이 필요하지 않은 경우도 많음 (그럴때는 public final 필드를 사용 하도록)
- API를 변경하지 않고도 싱글턴 패턴을 포기할 수 있다는 것임
- 특징
-
싱글턴 클래스의 직렬화
-
싱글턴 클래스를 직력화 가능(Serializable) 클래스로 만들려면 implements Serializable을 추가하는 것만으로는 부족함
-
싱글턴 특성을 유지하려면 모든 필드를 transient로 선언하고 readResolve 메서드를 추가해야 함
-
그렇지 않으면 역직렬화 다 새로운 객체가 생기기 때문임
// 싱글턴 상태를 유지하기 위한 realResolve 구현 private Object readResolve() { // 동일한 Elvis 객체가 반환되도록 하는 동시에, 가짜 Elvis객체는 GC가 처리하도록 만든다. return INSTANCE; }
-
결론
-
원소가 하나뿐인 enum 자료형이야말로 싱글턴을 구현하는 가장 좋은 방법임
-
싱글턴 구현하는 방법(JDK 1.5 부터)
//Enum 싱글턴 - 이렇게 하는 것이 더 좋다. public enum Elvis { INSTANCE; public void leaveTheBuilding() { .. }; }
- 특징
- public 필드를 사용하는 구현법과 동등함
- 간결하고 직렬화가 자동으로 처리됨. 또한 리플렉션을 통한 공격에도 안전함
- 특징
끝으로
이 글이 도움이 되었다면, Google 광고 한번씩 클릭 부탁 드립니다. 🙏🙏🙏
광고 클릭은 많은 힘이 됩니다!
반응형
'프로그래밍 > EffectiveJava' 카테고리의 다른 글
(이펙티브 자바) 규칙18. 상속보다는 컴포지션을 사용하라 (0) | 2020.02.13 |
---|---|
(이펙티브 자바) 규칙 1. 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2020.02.11 |
(이펙티브 자바) 규칙6. 불필요한 객체 생성을 피하라 (0) | 2020.02.10 |
(이펙티브 자바) 규칙4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2020.02.06 |
(이펙티브 자바) 규칙53. null 대신 빈 배열이나 컬렉션을 사용하라 (0) | 2020.02.01 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 자바
- 배낭 여행
- 이펙티브
- git
- 배낭여행
- 일본 배낭여행
- effective java
- 일본여행
- JavaFX Table View
- TableView
- JavaFX
- java
- 스프링부트
- JavaFX Window Close
- 자전거
- 방통대 과제물
- 이펙티브자바
- JavaFX 종료
- windows
- 일본 여행
- JavaFX 테이블뷰
- 텐트
- 이펙티브 자바
- 자전거 여행
- 일본 자전거 여행
- 인텔리제이
- Java UI
- springboot
- intelij
- effectivejava
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함