본문 바로가기

Design Pattern

Singleton Pattern

Singleton pattern이란 ?

- 애플리케이션이 시작될 때 어떤 클래스가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 인스턴스를 만들어 사용하는 디자인패턴.

- 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나고 최초 생성 이후에 호출된 생성자는 최초에 생성한 객체를 반환한다. (자바에선 생성자를 private로 선언해서 생성 불가하게 하고 getInstance()로 받아쓰기도 함) 

 

Singleton pattern을 쓰는 이유 ?

- 고정된 메모리 영역을 얻으면서 한번의 new로 인스턴스를 사용하기 대문에 메모리 낭비를 방지할 수 있음 

- 싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스 이기 때문에 다른 클래스의 인스턴스 들이 데이터를 공유하기 쉽다 

- DBCP와 같이 공통된 객체를 여러개 생성해야 하는 상황에서 많이 사용한다. Thread Pool , cache, 사용자설정, 레지스트리 설정, log 등 

 

Singleton pattern diagram

1. 클라이언트는 getInstance() 메소드를 통해서 싱긅톤 객체를 요청함 

2. Singleton은 이미 생성된 객체가 없으면 새로 만들어줌

3.  이미 있던거 또는 새로 생성한 객체를 반환해 줌 

 

 

Singleton Pattern 구현 방법

Singleton pattern은 Initialization 시점에 따라 여러가지 방법으로 구현할 수 있다. 

 

1. Eager initialization( 이른초기화방식) 

- 싱글톤의 가장 기본적인 형태

- 클래스 인스턴스는 클래스 로딩 시점에 인스턴스를 생성 -> 메모리 효율이 비효율적이나 Thread-Safe 하다  

- 규모가 작은 프로젝트에서는 하기와 같이 사용 ( 싱글톤 객체 사용 유무와 상관없이 클래스 로딩되는 시점에 항상 싱글톤 객체가 생성되어 메모리를 잡고 있기 때문에 비효율적이다) 

public class EagerInitialization{

//private static으로 선언

  private static EagerInitialization instance = new   EagerInitialization();

   

   //생성자 private로 선언(외부에서 new 할 수 없도록) 

   private EagerInitialization() {

       System.out.printlnt("call EagerInitialization<<<<<");

  }

   

   //조회 method

   public static EagerInitializationgetInstance(){

       return instance;

  }

   

   public void print(){

       System.out.println("It's print() method in instance");

       System.out.println("instance hashCode > " + instance.hashCode());

  }

}

 

2. lazy initialization(늦은 초기화 방식)

- 클래스 인스턴스가 사용되는 시점에 인스턴스를 생성(Eager와 반대)

- instance가 null인 경우에만 new를 사용해 객체를 생성한다. 

- 객체가 필요할 때 인스턴스화를 시키기 때문에 메모리에 효율이 좋음

- 하지만 멀티쓰레드 방식이라면 같은 시점에 getInstance를 호출하면서 인스턴스가 두번 생길 위험이 있음. 즉 멀티쓰레드 방식에서는 Singleton의 철학이 깨질 수 있음

public class LazyInitialization{
 

  private static LazyInitialization instance;
   private LazyInitialization() {
  }
   
   public static LazyInitialization getInstance (){
       if(instance == null){
           instance = new LazyInitialization();
      }
       return instance;
  }
   
   public void print(){
       System.out.println("It's print() method in instance")
       System.out.println("instance hashCode > " + instance.hashCode());
  }
}

 

3. initialization on demand holder idiom(

- class안에 class를 두어 JVM의 Class Loader 매커니즘과 class가 로드되는 시점을 이용한 방법

- lazy initialization 방식을 가져가면서 thread간의 동기화 문제를 동시에 해결  

- 최초로 getInstance()메서드가 호출될 때 클래스 로더에 의해 싱글톤 객체를 생성하여 리턴 함. holder안에 선언 된 instance는 static이기 때문에 클래스 로딩 시점에 한번만 호출 된다. 

- final을 써서 다시 값이 할당되지 않도록 함.  

- 현재 JAVA의 Singleton은 거의 이 방법을 사용함 

public class InitializationOnDemandHolderIdiom {

 

    private InitializationOnDemandHolderIdiom(){

    }

     

    private static class SingleTonHolder{

        private static final InitializationOnDemandHolderIdiom instance = new InitializationOnDemandHolderIdiom();

    }

    public static InitializationOnDemandHolderIdiom getInstance(){

        return SingleTonHolder.instance;

    }

}

 

Spring과 Singleton

- 스프링에서는 Bean(Bean : 스프링이 관리하는 오브젝트)을 싱글톤으로 만들어서 관리함. 

- 기본적으로 Bean의 Scope는 싱글톤 스코프이며 컨테이너 내의 한개의 오브젝트만 만들어져서 강제로 제거하지 않으면 컨테이너가 살아있는한 계속 유지된다. 

- 스프링 컨테이너는 싱글톤 관리 컨테이너 이기도 하다. 평범한 자바 클래스를 싱글톤으로 활용하게 해준다는 뜻. 싱글톤 레지스트리 덕분에 싱글톤으로 사용될 클래스라도 public 생성자를 가질 수 있다. 

- 설정을 통해 singleton이 아닌 방식으로 객체를 관리할 수도 있음 

Singleton pattern vs Spring Singleton Scope 

- 싱글톤 패턴과 싱글톤 스코프는 다름!! 

- 싱글톤 pattern은 하나의 클래스로더 당 하나의 객체 

- Spring singleton은 하나의 컨테이너에 하나의 Bean 

- JAVA Singleton Pattern에서 공유 범위는 Class loader 기준이지만, Spring에서는 ApplicationContext가 기준

- Java Static으로 구현한 Singleton은 private 생성자를 가지기 때문에 상속, 다형성을 사용할 수 없으며 테스트가 어려움. 

- Spring은 싱글톤 레지스트리(applicationContext)를 사용해 서버 환경에서 싱글톤이 만들어지기 때문에 자바 코드로 구현한 싱글톤 패턴의 여러 단점을 보완 수 있음. 

 

 

 

출처 : https://reactiveprogramming.io/books/design-patterns/en/catalog/singleton

 

Introduction to Design Patterns - A practical approach

The most comprehensive book about design patterns, all written in English. Learn how to implement design pattern with real-world examples.

reactiveprogramming.io

출처 : https://n1tjrgns.tistory.com/177

 

Spring - 싱글톤 패턴(Singleton Pattern)

싱글톤 패턴(Singleton Pattern) 싱글톤 패턴이란? 기본전략 : 인스턴스가 사용될 때 똑같은 인스턴스를 만들어 내는 것이 아니라, 동일 인스턴스를 사용하게끔 하는 것. 프로그램상에서 동일한 커넥션 객체를 만..

n1tjrgns.tistory.com

출처  : https://joont.tistory.com/144

 

싱글톤과 스프링

싱글톤이란 무엇일까요 ? 이를 알기 위해선 먼저 오브젝트의 동일성과 동등성에 대해 아셔야합니다. 게시글 바로가기 > 동일성, 동등성 싱글톤이란 해당 클래스의 인스턴스가 하나만 만들어지는, 전역변수와 같은..

joont.tistory.com

출처 : https://www.javadevjournal.com/spring/spring-singleton-vs-singleton-pattern/

 

Spring Singleton vs Singleton Pattern

Learn the difference between Spring Singleton vs Singleton Pattern.A singleton bean in Spring and the singleton pattern are quite different.

www.javadevjournal.com

 

'Design Pattern' 카테고리의 다른 글

Composite pattern  (0) 2020.02.21
Strategy Pattern  (0) 2020.02.14