ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 싱글톤(Singleton)패턴1
    Web 개발/디자인 패턴 2023. 6. 17. 11:47

    싱글톤 패턴

    인스턴스를 오직 한개만 제공하는 클래스

     

    시스템 런타임, 환경세팅에 대한 정보 등, 인스턴스가 여러개 일 때 문제가 생길 수 있는 경우가 있다. 인스턴스를 오직 한개만 만들어 제공하는 클래스가 필요하다.

     

    private한 생성자와 static한 메서드를 이용한 구현 

     

    Settings.class

    public class Settings{
    
    }

     

    App.class

    public class App{
    	
        public static void mian(String[] args){
        	Settings setting = new Settings();
            Settings setting1 = new Settings();
        }
    }

    App이라는 class가 있고, Settings라는 class가 있다. 이때 App class에서 Settings class의 인스턴스를 얼마든지 만들 수 있다. 즉 Settings 타입의 인스턴스가 얼마든지 만들어질 수 있다는 것을 의미한다.

     

    public class App{
    	
        public static void mian(String[] args){
        	Settings setting = new Settings();
            Settings setting1 = new Settings();
            System.out.println(setting != settings1);
        }
    }

    두개의 다른 인스턴스를 만들면 두 인스터스는 같지 않다.

     

    public class Settings{
    	
        private Settings(){}
    }

    그러므로 싱글톤 패턴을 구현하려면 절대 new 연산자로 인스턴스를 생성하면 안된다. 자바에서 new를 사용해서 생성자를 만들지 못하게 하려면 private 생성자를 만들어주면 된다. 오직 Settings 클래스 안에서만 접근할 수 있는 생성자를 만들어 주는 것이다. 이렇게 되면 더이상 Settings 클라스 밖에서 새로운 Settings 타입의 인스턴스를 생성할 수 없다.

     

     

    public class Settings{
    	
        private Settings(){}
        
        public static Settings getInstance(){
        	return new Settings();
        }
        
    }

    이제 Settings 클래스 밖에서 인스턴스를 만들 수 없기 때문에 Settings 클래스 안에서 인스턴스를 만들어서 글로벌하게 접근가능 하도록 만들어야 한다. 글로벌 하게 접근 가능하게 만드는 방법은 static을 사용하는 것이다. static한 getInstance()메서드를 Settings 클래스안에 만들어 준다.

     

    public class App{
    	
        public static void mian(String[] args){
        	Settings setting = Settings.getInstance();
            Settings setting1 = Settings.getInstance();
            System.out.println(setting != settings1);
        }
    }

    하지만 getInstance()메서드를 만들때 Settings 클래스에서 new Setting()를 사용한 것도 문제가 된다. Settings.getInstance()를 부를대 마다 새로운 Settings 클래스의 인스턴스가 생성되어 반환되기 때문이다.

     

    해결방법

    public class Settings{
    	
        private static Settings instance;
        
        private Settings(){}
        
        public static Settings getInstance(){
        	if(instance == null){
            	instance = new Settings();
            }
            
            return instance;
        }
        
    }

    Settings 인스턴스가 null일때만 new 연산자로 Settings 인스턴스를 만들어주고 이미 존재한다면 이미 존재하는 Settings instance를 반환한다.

     

    public class App{
    	
        public static void mian(String[] args){
        	Settings setting = Settings.getInstance();
            Settings setting1 = Settings.getInstance();
            System.out.println(setting -== settings1);
        }
    }

    이렇게 하면 getInstance()메서드를 부를 때 마다 같은 인스턴스가 반환 된다.

     

    ❗하지만 private한 생성자와 static한 메서드를 이용한 구현 방법에는 치명적인 문제가 존재한다. 보통 웹 어플리케이션을 만들 멀티 쓰레드를 사용하게 된다. 즉 여러 쓰레드가 동시에 접근할 수 있는 코드가 된다. 그런 환경에서 private한 생성자와 static한 메서드를 이용한 구현 방법은 안전하지 못하다.

     

    [출처 - https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard]

     

    댓글

Designed by Tistory.