ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 생성자나 열거타입으로 싱글턴임을 보증하라
    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;
        
        // ...
    }

     

    이 방법을 이용하면 더 간결하고 추가적인 노력 없이 직렬화 할 수 있습니다. 리플렉션에서도 안전하고요. 책에서는 대부분의 경우 원소가 하나뿐인 열거 타입이 싱글턴을 만드는 가장 좋은 방법이라고 소개하고 있습니다. 

     

    하지만 다른 클래스를 상속해야 한다면 이 방법은 사용할 수 없습니다.

    반응형
Designed by Tistory.