관리 메뉴

개발자의 스터디 노트

자바 디자인패턴 - 싱글톤(Singleton) 본문

자바/인스턴트코드

자바 디자인패턴 - 싱글톤(Singleton)

박개발씨 2022. 4. 11. 23:28

싱글톤 패턴이란?

 - 클래스를 최초 한번만 메모리(static)에 할당하고 그 메모리에 객체를 만들어 사용하는 패턴

 - 생성자를 반복적으로 호출해도 최초 생성된 객체를 반환해주는것.

 

기본적인 싱글톤 구현 방법

public class SingletonClass {
	//Instance
    private static SingletonClass instance = new SingletonClass();
    
    //생성자를 private로 만들어 외부에서 객체를 생성하지 못하게 한다.
    //private construct
    private SingletonClass() {}
    
    //Instance 반환
    public static SingletonClass getInstance(){
    	return instance;
    }
 }

 

싱글톤 패턴을 사용하는 이유

 - 단 한번의 객체 생성으로 재 사용이 가능하기 때문에 자원 낭비를 방지 할 수 있습니다.

 - 싱글톤 객체는 static(정적속성) 객체이기 때문에 다른 객체와 공유기 좋습니다.

 

싱글톤의 단점

 - 싱글톤 객체의 역할이 복잡해질 경우 단른 객체간의 결합도가 높아져 객체지향 설계에 어긋나게 됩니다.

 - private 생성자를 가지고 있어 상속이 불가능 합니다.

 - 서버 환경에서는 싱글톤이 1개만 생성됨을 보장하지 못합니다.

 - 전역 상태를 만들 수 있기 때문에 바람직하지 못합니다. 아무 객체나 자유롭게 접근하고 수정하며 공유되는

   전역 상태는 객체지향 프로그래밍에서 권장되지 않습니다.

 

다양한 싱글톤 구현 방법

 

static block

 - static 블럭을 사용할 경우 클래스가 로딩될 때 한번만 실행을 하게 되는 특성을 사용합니다. 하지만 인스턴스가 사용되는 시점이 아닌 클래스 로딩 시점에 실행이 됩니다.

public class SingletonClass {
	//Instance
    private static SingletonClass instance;
    
    //생성자를 private로 만들어 외부에서 객체를 생성하지 못하게 한다.
    //private construct
    private SingletonClass() {}
    
    static{
    	try{
        	instance = new SingletonClass();
        }catch(Exception e){
        	throw new RuntimeException("Create instance fail. error msg = " + e.getMessage());
        }
    
    //Instance 반환
    public static SingletonClass getInstance(){
    	return instance;
    }
 }

 

 

lazy init(게으른 초기화)

 - static 방법에서 개선하여 클래스 로딩 시점이 아닌 인스턴스가 필요하여 요청할 때 생성되는 형태입니다.

 - 멀티 쓰레드 환경에서 동시에 getInstance() 메서드를 호출하게 되면 인스턴스가 두 번 생성되는 문제가 발생할 수 있습니다.

public class SingletonClass {
	//Instance
    private static SingletonClass instance;
    
    //생성자를 private로 만들어 외부에서 객체를 생성하지 못하게 한다.
    //private construct
    private SingletonClass() {}
        
    //Instance 반환
    public static SingletonClass getInstance(){
    	if(instance == null){
        	instance = new SingletonClass();
        }
    	return instance;
    }
 }

 

 

Thread safe lazy init(동기화 블럭 게으른 초기화)

 - synchronized 키워드를 붙여 동기화를 통해 쓰레드에서 동시 접근에 대한 문제를 방지 하였습니다. 하지만 synchronized 키워드는 성능 저하를 발생시킵니다.

public class SingletonClass {
	//Instance
    private static SingletonClass instance;
    
    //생성자를 private로 만들어 외부에서 객체를 생성하지 못하게 한다.
    //private construct
    private SingletonClass() {}
        
    //Instance 반환
    public static synchronized SingletonClass getInstance(){
    	if(instance == null){
        	instance = new SingletonClass();
        }
    	return instance;
    }
 }

 

 

Holder

 - JVM의 클래스 로더 메커니즘과 클래스의 로드 시점을 이용하여 내부 클래스를 통해 생성 시킴으로써 쓰레드 간의 동기화 문제를 해결하였습니다. JAVA에서 싱글톤 생성에 가장 대표적인 방법입니다.

public class SingletonClass {
	
    //생성자를 private로 만들어 외부에서 객체를 생성하지 못하게 한다.
    //private construct
    private SingletonClass() {}
    
    private static class InnerInstanceClazz(){
    	private static final SingletonClass instance = new SingletonClass();
    }
        
    //Instance 반환
    public static synchronized SingletonClass getInstance(){    	
    	return InnerInstanceClazz.instance;
    }
 }

 

 

스프링에서의 싱글톤

 - 스프링 컨테이너는 등록된 스프링 빈들을 모두 싱글톤으로 관리합니다.

 - @Bean 어노테이션으로 스프링 빈으로 등록하여 싱글톤으로 관리 할 수 있습니다.