IT/Programming / / 2023. 4. 28. 09:21

<Effective Java> RULE 3 private 생성자나 enum자료형은 싱글턴 패턴을 따르도록 설계하라.

반응형

 

싱글턴은 객체를 하나만 만들 수 있는 클래스다. 하지만 클래스를 싱글턴으로 만들면 클라이언트 테스트하기는 어렵다.

 

JDK 1.5이전 싱글턴 구현하는 방법 2가지

1. 정적 멤버 이용

// public final 필드를 이용한 싱글턴
public class Elvis{
public static final Elvis INSTANCE = new Elvis();
private Elvis() {..}

public void leaveTheBuilding() {..}
}
 

주의) AccessibleObject, setAccessible 메서드의 도움을 받아 권한 획득한 클라이언트는 리플렉션 기능을 통해 private 생성자를 호출할 수 있다. (규칙 53) 이런종류의 공격을 방어하고자 한다면 두번 째 객체를 생성하라는 요청을 받으면 예외를 던지도록 생성자를 고쳐야 한다.

 

2. 정적 팩터리 메서드를 이용

// 정적 팩토리 싱글턴
public class Elvis{
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() {..}
    public static Elvis getInstance() { return INSTANCE; }
    
    public void leaveTheBuilding() {..}
}
 

JVM은 정적 팩토리 메서드를 거의 항상 인라인으로 처리해 버리기 때문에 성능에 기대를 하는것은 좋지 않다.

인라인?

- 말 그대로 함수의 내용을 line 내부에 담아주는 함수다. 일종의 치환이다.

 

인라인 장점

- 기본적으로 속도가 빨라진다.

함수의 실행 흐름이 다른 곳으로 이동했다가 돌아오는 것이 아니라, 하나의 함수 내에서 모두 처리하게 되므로 속도상의 이득을 볼 수 있다.

하지만 긴 내용을 inline으로 선언하는 것은 좋지 않다.

 

인라인 단점

- 프로그램의 크기가 커진다.

프로그램의 크기가 커진다는 것은 메모리에 한번에 많은 양의 데이터가 올라간다는 뜻이며, 그로 인해서 컨텍스트 스위칭이 자주 일어날 수 있다.

결국 빠른 속도를 얻고자 작성한 inline함수가 오히려 속도를 떨어뜨릴 수 있다는 단점이 있다.

이것이 긴 내용을 inline으로 선언하지 말라고 한 이유다.

출처 입력

 

팩토리 메서드의 장점

API를 변경하지 않고도 싱글턴 패턴을 포기할 수 있다.

스레드 마다 별도의 객체를 반환하게도 할 수 있다.

(규칙 27) 제네릭 타입을 수용하기 쉽다.

 

 

1번과 2번의 싱글턴의 방법으로는 직렬화 하기 위해서 implements Serializable을 추가하는것으로 부족하다.

싱글턴을 유지하기 위해서는 모든 필드를 transient로 선언하거나 readResolve메서드 추가(규칙 77)

 

JDK 1.5이상에서 사용가능한 싱글턴
 
// Enum
public enum Elvis{
    INSTANCE;
    
    public void leaveTheBuilding() {..}
}
 

좀더 간결하며, 직렬화가 자동으로 처리된다.

리플렉션에도 안전하다.

원소가 하나뿐인 Enum자료형이야 말로 싱글턴을 구현하기 가장 좋은 방법이다.

 

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유