[디자인패턴] Singleton Pattern (싱글톤 패턴)

Song_Song·2021년 12월 15일
0

Singleton 패턴

오로지 한 개의 인스턴트만 제공하는 클래스



싱글톤을 구현하는 첫 번째 방법

  • Eager Initialization(이른 초기화)
  • 클래스 로드 시에 new 가 실행되어 항상 1개의 인스턴스를 가지게 된다.
  • JDK 에서 제공하는 Singleton은 (ex. Collection empty, ValueOf..) 이 방법을 사용하고 있다.
public class Singleton1 {
   /* 외부에서 이 맴버변수로 직접 접근하여 사용할 수 있도록 public static final 로 사용하기도 한다. */
   private static Singleton1 singleton1 = new Singleton1(); // 맴버변수로 자기 자신의 클래스의 인스턴스를 가진다.

   private Singleton1(){ // private 생성자를 사용하여 외부에서 인스턴스를 생성하지 못하게 한다. (현재 클래스에서만 인스턴스 생성 가능)
   }

   public static Singleton1 getInstance(){ // getInstance() 메소드를 통해 객체를 static하게 가져온다.
       return singleton1;
   } 


싱글톤을 구현하는 두 번째 방법

  • 클래스 로드시에 인스턴스를 생성하는 첫 번째 방법과는 다르게, getInstance()가 처음 호출될 때 인스턴스가 생성된다.
  • synchronized 키워드를 사용하였기 때문에 성능은 비교적 안 좋지만 인스턴스를 사용하지 않을 때는 인스턴스를 생성하지 않는다는 장점이 있다.
public class Singleton2 {
    private static Singleton2 singleton2;

    private Singleton2(){
    }

    /* synchronized : 현재 데이터를 사용하고 있는 해당 스레드를 제외한 다른 스레드들은 접근할 수 없게 막음 => 데이터의 thread-safe */
    public static synchronized Singleton2 getInstance(){
        if(singleton2 == null){
            singleton2 = new Singleton2();
        }
        return singleton2;
    } 


싱글톤을 구현하는 세 번째 방법

  • 성능적인 측면도 고려하면서 인스턴스가 필요하지 않을 때 아예 생성하지 않는 장점을 혼합한 방식
  • if 문을 두 번 사용하여 여러 개의 쓰레드가 동시에 집입 할 때 두 번 분기를 하는 방식
 public class Singleton3 {

    /** volatile : 변수를 Main Memory에 저장한다는 뜻 => 변수 값 불일치 해결 (변수의 원자성 보장) Java 1.5
     * 일반 변수는 멀티쓰레드 환경에서 성능 향상을 위해 Main Memory에서 읽은 변수를 CPU Cache에 저장하게 되는데, 이런 경우 다중 쓰레드가 값을 읽어올 때 변수 값 불일치 문제가 발생할 수 있다.
     * CPU Cache 보다 Main Memory 비용이 더 크기 때문에 성능에 영향을 미치긴 한다.
     * 하나의 쓰레드가 Write 하고 나머지 쓰레드는 Read를 하는 경우에만 적합하다
     * 여러 쓰레드가 Write 하는 상황에서는 synchronized 변수를 사용
     */
    private volatile static Singleton3 singleton3;

    private Singleton3(){}

    public static Singleton3 getInstance(){
        if (singleton3 == null){ // 인스턴스가 생성 된 이후라면 synchronize 까지 아예 가지 않음 => 성능 저하 문제 해결
            synchronized (Singleton3.class){ // 동기화 블록
                if (singleton3 == null){
                    singleton3 = new Singleton3(); // 처음으로 진입한 쓰레드만 인스턴스를 생성
                }
            }
        }
        return singleton3;
    }
}


싱글톤을 구현하는 네 번째 방법

  • Inner Class 를 사용허는 방법
  • 앞 3가지와는 다르게 Singleton 클래스가 자기 자신 타입의 맴버변수를 가지고 있지 않고 Inner Class가 가지고 있다.
  • Inner Class가 호출되는 시점에 최초로 생성이 되기 때문에 성능적인 이슈도 없고 인스턴스가 필요하지 않다면 생성하지 않는다.
public class Singleton4 {

    private Singleton4(){}

    private static class SingletonHolder{
        static final Singleton4 singleton4 = new Singleton4();
    }

    public static Singleton4 getInstance(){
        return SingletonHolder.singleton4;
    }
}

참고 블로그 : https://gregorio78.tistory.com/122

profile
성장을 위한 정리 블로그

0개의 댓글