일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 접근지시자
- 함수형 인터페이스
- 정렬
- 자바스터디
- 제네릭 타입
- yield
- 로컬 클래스
- 브릿지 메소드
- 프리미티브 타입
- 합병 정렬
- raw 타입
- github api
- junit 5
- System.out
- annotation processor
- throwable
- 상속
- 항해99
- 자바할래
- System.in
- Study Halle
- docker
- 바운디드 타입
- 익명 클래스
- System.err
- 제네릭 와일드 카드
- auto.create.topics.enable
- 스파르타코딩클럽
- 람다식
- Switch Expressions
Archives
- Today
- Total
코딩하는 털보
이펙티브 자바, 아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 본문
이펙티브 자바, 아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라
싱글턴 : 인스턴스를 오직 하나만 생성할 수 있는 클래스
public static final
인스턴스public class Printer { private final String name = "yoyo printer"; private final String owner = "tuna"; public static final Printer INSTANCE = new Printer(); private Printer() { } public void print(String in) { System.out.println("========================="); System.out.println("this is "+this.owner+"'s "+this.name); System.out.println("========================="); System.out.println(in); } }
Printer myprinter = Printer.INSTANCE; myprinter.print("hello");
생성자는 private로 감춰두고, 인스턴스에 접근할 수 있도록 public static final 필드를 만들어준다.
private 생성자는 INSTANCE 필드가 처음 초기화 될 때 한 번만 호출되어 인스턴스가 하나임이 보장된다.
그러나 권한이 있는 클라이언트는 리플렉션 API를 통해 private를 호출할 수 있기 때문에 생성자에서 이를 예외처리 해야한다.private Printer() { count++; if ( count != 1) { throw new IllegalStateException("싱글톤을 더 생성할 수 없습니다."); } }
이 방식의 장점은 이 클래스가 싱글턴임이 API에 명백하게 드러나고 코드가 보다 간결하다는 점이다.
정적 팩토리 메서드 제공하기
public class Printer { private final String name = "yoyo printer"; private final String owner = "tuna"; public static final Printer INSTANCE = new Printer(); private Printer() { } public static Printer getInstance() { return INSTANCE; } public void print(String in) { System.out.println("========================="); System.out.println("this is "+this.owner+"'s "+this.name); System.out.println("========================="); System.out.println(in); } }
Printer myprinter = Printer.getInstance(); myprinter.print("hello");
정적 팩토리 메서드 방식의 장점
싱글턴을 해제하기 쉽다.
public static Printer getInstance() { return new Printer(); }
정적 팩토리를 제네릭 싱글턴 팩토리로 만들수 있다.
@SuppressWarnings("unchecked") public static <T> Printer<T> getInstance() { return (Printer<T>) INSTANCE; }
정적 팩토리의 메서드 레퍼런스를 함수형 인터페이스 Supplier의 구현체처럼 사용할 수 있다.
Supplier<Printer> printerSupplier = Printer::getInstance; printerSupplier.get().print("hello");
원소가 하나인 열거 타입 사용하기
위 두가지 방식의 단점은 리플렉션을 통한 private 생성자 접근을 방어해야하고 직렬화에 부가적인 기능을 더해야 한다는 것이다.
대신 원소가 하나인 열거 타입을 사용하면 이런 문제가 전혀 없기 때문에 대부분의 상황에서는 싱글턴을 만드는 가장 좋은 방법이 된다.public enum Printer { INSTANCE; private final String name = "yoyo printer"; private final String owner = "tuna"; public void print(String in) { System.out.println("========================="); System.out.println("this is "+this.owner+"'s "+this.name); System.out.println("========================="); System.out.println(in); } }
다만 조금 부자연스러워 보이고 Enum 외의 클래스를 상속할 수 없다는 단점이있다.
Comments