책/Effective Java

[이펙티브 자바] 아이템3: private 생성자나 열거 타입으로 싱글턴임을 보증하라

2022. 4. 18. 19:02
목차
  1.  
  2. 싱글턴 만드는 방법 주된 2가지
  3. 각 방법 장점
  4. 문제: 방법1과 방법2는 직렬화하기 위해서 추가적인 노력이 필요함
  5. 방법3
본문은 Effective Java를 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.

 

싱글턴 만드는 방법 주된 2가지

방법1 - final 필드)

public static final INSTANCE

 

방법2 - 정적 팩터리 메서드)

private static final INSTANCE + public static getInstance

 

  • 방법1과 방법2의 공통점
    • private 생성자 이용
    • 유일한 인스턴스에 접근할 수 있는 수단으로 public static 멤버 마련
    • 생성자가 두 번 호출될 시에 방어가 필요함 <- 클라이언트측에서 리플렉션을 이용해 호출할 경우

 

각 방법 장점

방법1)

  • 1. 해당 클래스가 싱글턴임이 API에 명백히 드러남
  • 2. 간결함

방법2)

  • 1. API를 바꾸지 않고 싱글턴이 아니게 변경할 수 있다
    • 방법1의 경우엔 필드가 public으로 열려있어 Class.INSTANCE와 같은 형태로 객체를 직접 참조하고 있다.
    • 하지만 방법 2는 객체를 직접 참조하는 것이 아니라 메소드를 통해 참조하고 있다.
    • 메서드 내부에서 return new Instance();와 같은 형태로 바꿔준다면 싱글턴이 아니라 새로운 객체를 생성하여 반환하는 식으로 API를 변경할 수 있다.
  • 2. 정적 팩터리를 제네릭 싱글턴 팩터리를 만들 수 있다(아이템30)
  • 3. 정적 팩터리의 메서드 참조를 공급자로 사용할 수 있다
    • Elvis::getInstance를 Supplier<Elvis>로 사용한다는 뜻
    • Supplier<T>란 함수형 인터페이스로서, get()이라는 추상 메서드가 있다
      • get()메서드에 getInstance()걸림
        • 즉, getInstance() 메서드가 Supplier<T>의 구현체처럼 쓰일 수 있음
        • Supplier<INSTANCE> supplier = INSTANCE::getInstance; <- 이런 형태로 사용 가능하다.. 
      • Supplier는 매개변수를 받지 않고 단순히 '어떤 것'을 반환한다
      • 추상 메서드 get()을 통해 Lazy Evaluation이 가능하다는 장점이 있다
  • 위의 장점들이 필요없다면 방법1을 택하라

 

문제: 방법1과 방법2는 직렬화하기 위해서 추가적인 노력이 필요함

  • 참고: https://www.youtube.com/watch?v=3iypR-1Glm0&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech
  • 기본적으로 직렬화에서 직렬화할 때 객체 != 역직렬화된 객체
    • 따라서 싱글턴 클래스를 직렬화하면 싱글턴의 성격을 잃어버림
  • 따라서 readResolve 메서드를 정의하여 싱글톤 객체를 반환하게 해야함
    • readObject()가 반환된 이후에 readResolve()가 호출됨 -> 객체를 바꿈
  • 인스턴스 필드는 transient 키워드를 붙여야 한다 => 이유가 궁금하면 '도둑클래스' 키워드로 검색

 

방법3

  • public 필드 방식과 유사하지만 직렬화하기 쉬움
  • 아주 복잡한 직렬화 상황이나 리플렉션 공격에서도 제2의 인스턴스가 생기는 일을 완벽히 막아줌
  • 조금 부자연스러워 보일 지라도 원소가 하나뿐인 열거 타입이 싱글턴을 만드는 가장 좋은 방법
  • 단, 만들려는 싱글턴이 Enum 외의 클래스를 상속해야 한다면 이 방법은 사용 불가, 대신 열거 타입이 다른 인터페이스를 구현하도록 선언
  • 개인적으로 이렇게 선언된 싱글턴은 처음 봤다.. 이 부분은 좀 더 공부가 필요할 것 같다
저작자표시 비영리 (새창열림)

'책 > Effective Java' 카테고리의 다른 글

[이펙티브 자바] 아이템6: 불필요한 객체 생성을 피하라  (0) 2022.04.18
[이펙티브 자바] 아이템5: 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라  (0) 2022.04.18
[이펙티브 자바] 아이템4: 인스턴스화를 막으려거든 private 생성자를 사용하라  (0) 2022.04.18
[이펙티브 자바] 아이템2: 생성자에 매개변수가 많다면 빌더를 고려하라  (0) 2022.04.18
[이펙티브 자바] 아이템1: 생성자 대신 정적 팩터리 메서드를 고려하라  (0) 2022.04.18
  1.  
  2. 싱글턴 만드는 방법 주된 2가지
  3. 각 방법 장점
  4. 문제: 방법1과 방법2는 직렬화하기 위해서 추가적인 노력이 필요함
  5. 방법3
'책/Effective Java' 카테고리의 다른 글
  • [이펙티브 자바] 아이템5: 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
  • [이펙티브 자바] 아이템4: 인스턴스화를 막으려거든 private 생성자를 사용하라
  • [이펙티브 자바] 아이템2: 생성자에 매개변수가 많다면 빌더를 고려하라
  • [이펙티브 자바] 아이템1: 생성자 대신 정적 팩터리 메서드를 고려하라
코택
코택
코택
TaxFree
코택
전체
오늘
어제
  • 분류 전체보기 (369)
    • Spring (29)
      • Spring (18)
      • 스프링 핵심 원리 - 고급편 (11)
    • Spring Batch (4)
    • JPA (4)
    • CS (89)
      • 자료구조 (2)
      • 네트워크 (5)
      • 운영체제 (1)
      • 데이터베이스 (4)
      • SQL (7)
      • 알고리즘 이론 (4)
      • 알고리즘 문제 풀이 (66)
    • 웹 (28)
      • React.js (4)
      • Next.js (1)
      • Node.js (14)
      • FastAPI (4)
      • Django (5)
    • 프로그래밍 언어 (45)
      • Python (5)
      • Java + Kotlin (29)
      • JavaScript + TypeScript (11)
    • 테스트코드 (26)
      • ATDD, 클린 코드 with Spring (4)
      • 이규원의 현실 세상의 TDD: 안정감을 주는 코드.. (20)
    • 인프라 (6)
      • AWS (2)
      • Kubernetes (4)
    • 트러블슈팅 (25)
    • 책 (89)
      • Effective Java (54)
      • Effective Kotlin (14)
      • 도메인 주도 개발 시작하기: DDD 핵심 개념 정.. (11)
      • 웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 (6)
      • 도메인 주도 설계 첫걸음 (4)
    • Git (10)
    • 회고 (5)
    • etc (8)

블로그 메뉴

  • 홈
  • 방명록
  • 관리
  • GitHub
  • LinkedIn

공지사항

  • 스킨 관련

인기 글

태그

  • 백준
  • 장고
  • 브루트포스
  • Git
  • mysql
  • atdd
  • http
  • 그래프
  • fastapi
  • 파이썬
  • 깊이 우선 탐색
  • BOJ
  • Shortest Path
  • dp
  • 그래프 탐색

최근 댓글

최근 글

hELLO · Designed By 정상우.
코택
[이펙티브 자바] 아이템3: private 생성자나 열거 타입으로 싱글턴임을 보증하라
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.