-
생성자나 열거타입으로 싱글턴임을 보증하라language/JAVA 2021. 1. 29. 16:23반응형
이펙티브 자바에서 소개하는 싱글턴을 만드는 방법은 다음 세 가지이다.
public class Item3 { public static final Item3 INSTANCE = new Item3(); private Item3() {} // ... }
첫번째 방법은 생성자를 private 으로 감추고 유일한 인스턴스에 접근할 수 있는 수단으로 public static final 멤버를 하나 만드는 것이다. 생성자는 초기화 할 때 딱 한번만 호출되기 때문에 이 클래스의 인스턴스는 시스템 전체에 하나뿐임을 보증할 수 있다.
물론 리플렉션을 통해 생성자를 호출할 수는 있지만 생성자에서 예외를 던지도록 만들어서 방어할 수있다. 이 방법은 싱근턴임을 명확하게 파악할 수 있고 비교적 코드가 간결해 지는 장점이 있다.
public class Item3 { private static final Item3 INSTANCE = new Item3(); private Item3() {} public static Item3 getInstance() { return INSTANCE; } // ... }
두번째 방법은 역시 생성자를 private 으로 감추고 INSTANCE 를 private 으로 숨긴다. 대신 정적 팩터리 메소드를 제공한다. getInscance 메소드는 항상 같은 인스턴스를 반환하기 때문에 역시 인스턴스가 하나뿐임을 보증한다. 리플렉션을 통한 생성은 첫번째 방법과 마찬가지로 막을 수 있다.
이 방법은 싱글턴이 아닌 클래스로 변경할 때 이점을 가진다. 또 제네릭을 사용할 수 있다.
public class Item3 implements Serializable { private static final Item3 INSTANCE = new Item3(); private Item3() {} public Item3 getInstance() { return INSTANCE; } // ... }
위 두 방법의 단점은 직렬화를 위해 Serializable 을 구현할 때 발생한다. 직렬화된 인스턴스를 역직렬화할 때 마다 새로운 인스턴스가 만들어지기 때문이다. 이를 방어하기 위해서는 모든 인스턴스필드를 transient 선언하고 readResolve 메서드를 제공해야한다.
private Object readResolve() { return INSTANCE; }
마지막 방법은 원소가 하나인 열거 타입을 선언하는 것이다.
public enum Item3 { INSTANCE; // ... }
이 방법을 이용하면 더 간결하고 추가적인 노력 없이 직렬화 할 수 있습니다. 리플렉션에서도 안전하고요. 책에서는 대부분의 경우 원소가 하나뿐인 열거 타입이 싱글턴을 만드는 가장 좋은 방법이라고 소개하고 있습니다.
하지만 다른 클래스를 상속해야 한다면 이 방법은 사용할 수 없습니다.
반응형'language > JAVA' 카테고리의 다른 글
추상화(Abstraction), 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism) (0) 2023.04.25 Inner Class 를 쓸때는 static 으로 만들자 (0) 2023.03.24 [이펙티브 자바] 생성자 대신 정적 팩터리 메서드를 고려하라 (0) 2021.01.28 Stream, generate(), limit(), distinct(), sorted() (0) 2021.01.24 JAVA Enum(열거 타입) 값 비교하기 (0) 2021.01.22