최근에 싱글톤 디자인 패턴 , Java에서 이를 구현하는 방법 및 용도에 대해 자세히 살펴보았습니다. 그러나 Java가 기본적으로 자체 싱글톤과 함께 제공된다고 말하면 어떻게 됩니까? 흥미가 있습니까? 그럼 다이빙합시다.

이미 Enum 클래스 에 대해 알고 있을 것입니다 . 그것은 당신이 알아야 할 특별한 기능이 있습니다. 특히 Enum은 싱글톤 디자인 패턴을 구현합니다. 이 옵션은 공용 필드 와 관련된 싱글톤 접근 방식과 거의 동일합니다 .

열거형으로서의 싱글톤:


public enum Device {   
    PRINTER	
} 
    

공용 변수로서의 싱글톤:


public class Printer {   
    public static final Printer PRINTER = new Printer();   
    private Printer() {
    }
//…
}
    

열거 접근 방식은 자체 구현을 작성할 필요가 없기 때문에 공개 필드 접근 방식보다 더 간결합니다. 가장 중요한 것은 열거형이 직렬화에 문제가 없다는 것입니다.

열거형의 직렬화는 일반 객체와 다르게 작동합니다. 열거형 이름의 값만 직렬화됩니다. 역직렬화 중에 메서드는 역직렬화된 이름과 함께 사용되어 인스턴스를 가져옵니다. 또한 enum은 반사 공격 으로부터 사용자를 보호할 수 있습니다 .

Reflection API를 살펴보는 두 번째 모듈의 수업에서 리플렉션에 대해 자세히 알아볼 것입니다 .

Java는 enum의 인스턴스화를 금지합니다. 이는 Constructor 클래스의 newInstance 메서드 구현 에 적용된 제한 사항으로 , 리플렉션을 통해 객체를 생성할 때 자주 호출됩니다.

Constructor.newInstance 에서 발췌한 코드 . 열거형을 만드는 데 사용됩니다 .


if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
    

열거형을 사용하여 싱글톤을 만드는 단점은 다음과 같습니다.

  • 개체가 즉시 생성되고 초기화를 지연할 수 없기 때문에 지연 초기화가 부족합니다.

  • 다른 클래스는 확장할 수 없습니다. 즉, 다른 클래스를 상속해야 하는 경우 열거 형을 싱글톤으로 사용하는 것은 작동하지 않습니다. 이러한 경우 정적 메서드 또는 공용 변수와 같이 이미 익숙한 다른 구현 옵션으로 전환해야 합니다.

  • enum을 싱글톤으로 사용하는 경우 하나의 enum 필드 만 사용할 수 있습니다 .


public enum Device extends Electricity { 
    PRINTER 
}
    

이 코드는 컴파일 오류를 발생시킵니다.

enum에는 확장 절이 허용되지 않습니다.

그러나 인터페이스를 구현해야 하는 경우 enum이 인터페이스를 구현할 수 있으므로 문제가 없습니다 .


public enum Device implements Electricity { 
    PRINTER 
}
    

상속을 사용할 필요가 없다면 enum 을 통해 싱글톤 패턴을 구현하는 것이 가장 좋습니다 . 이것을 권장하는 것은 우리만이 아닙니다. Joshua Bloch 자신도 권장합니다 .

이 구현 방식은 편리함, 소형화, 즉시 사용 가능한 직렬화, 반사 공격으로부터의 보호, 고유성 등 좋은 싱글톤에 필요한 모든 것을 제공합니다!