티스토리 뷰

Programing/DesignPattern

Singleton 패턴

오통 2016. 8. 24. 14:07

Singleton 패턴이란?


  • 하나의 instance만 생성하는 것을 보장해 주는 패턴
  • 어떠한 instance를 사용할 때 매번 새로운 instance를 생성하는게 아니라, 하나의 instance만 생성하여 동일 instance를 계속 사용하는 방법이다.
  • 주로 설정관리를 위한 manager, controller 같은 애들은 하나의 instance를 생성하여 사용하므로 singleton 패턴을 이용한다





다양한 구현 방법



A) class load 시점에 instnace 생성



public class SingletonA {
// JVM에 의해 SingletonA class가 load 될 때 instance 생성.
private static SingletonA instance = new SingletonA();

public static SingletonA getInstance() {
    return instance;
}

private SingletonA() {
}
  • SingletonA class의 생성자가 private으로 외부에서 생성하여 사용할 수 없음. (instance 변수 역시 private으로 외부에서 접근 불가능.

  • SingletonA.getInstance() 와 같은 method를  통해 instance를 얻을 수 있음.

단점
class load time에 instance 생성 되므로 사용하지 않는 instance도 모두 메모리에 적재되며, 생성시 exception 발생에 대해 control 할 수 없음.


* JVM의 클래스 초기화 시점

 - T가 클래스이며 T의 인스턴스가 생성될 때

 - T가 클래스이며 T에서 선언한 정적 메서드가 호출 되었을 때

 - T에서 선언한 정적 필드에 값이 할당 되었을 때.

 - T에서 선언한 정적 필드가 상수가 아니며 사용 되었을 때

 - T가 최상위 클래스(상속 관계에서)이며 T안에 위치한 assert 구문이 실행 되었을 때


B) Lazy initialization



public class SingletonB {
private static SingletonB instance;
// 실제 SingletonB.getInstance()를 호출 하는 시점에 instance 생성.
public static SingletonB getInstance() {
    if (instance == null) {
        instance = new SingletonB();
    }

    return instance;
}

private SingletonB() {
}

단점

- lazy initialization으로 실제 instance를 사용할 때 생성하여 A보다 효율적이지만, multi thread 환경에서는 하나의 instance를 보장 할 수 없음.


C) Thread safe initialization



public class SingletonC {
private static SingletonC instance;
// synchronize 로 동기화
public synchronize static SingletonC getInstance() {
    if (instance == null) {
        instance = new SingletonC();
    }

    return instance;
}

private SingletonC() {
}


단점

- 수많은 thread에서 getInstance를 호출 하면 synchronize 로 인해 성능 저하 발생


D) DCL(Double Checked Locking)


public class SingletonD {
// volatile 으로 변수의 읽기/쓰기 연산의 원자성 보장 해줘야 함.
private volatile static SingletonD instance;
// 동기화 필요한 영역을 최소화 함. 
public static SingletonD getInstance() {
  if (instance == null) {
    syncronize (this) {
      if (instance == null) {
        instance = new SingletonD();
      }
    }
  }
  return instance;
}

private SingletonD() {
}

단점
JDK 1.5 미만에서는 정상동작하지 않을 수 있음.
- A thread가 new SingletonD() 에서 instance 생성 중일 때. (메모리생성 초기화 등 JVM에 의해 여러작업이 이루어 지는데, 메모리생성만 해도 instance는 null 이 아님. 그러나 초기화 되지 않은 상태)
B thread가 getInstance() 에 접근하여 instance를 return 하고 사용함. instnace가 초기화 되지 않았으므로 error 발생.
- 변수에 volatile 을 명시 함으로써 원자성을 확보하게 되고 정상 instance 사용을 보장함.
- JDK 1.5미만 의 경우 volatile이 원자성을 보장하지 않음. 1.5이상에서만 정상동작.



E) initialization on demand holder idiom



public class SingletonE {
// getInstance() 시, JVM에 의해 InnerClass가 loading 되면서 instance 생성.
// JVM에 의해 synchronize 보장.
private static SingletonE getInstance() {
  return SingletonHolder.singletonE;
}
  private static class SingletonHolder() {
    private static final singletonE = new SingletonE();
  }
}
- lazy initialization 과 thread safe 보장.

결론

- Singleton pattern을 사용할 때가벼운 program의 경우 그리고 lazy initialization이 꼭 필요하지 않은 경우는 A 방식lazy initialization이 꼭 필요한 경우 D, E 방식을 사용하자. (단 D의 경우 JDK 1.5이상 version이어야 함.)


참고 site
https://blog.seotory.com/post/2016/03/java-singleton-pattern
http://blog.daum.net/smufu/3



'Programing > DesignPattern' 카테고리의 다른 글

Template Method 패턴  (0) 2016.08.30
Composite 패턴  (0) 2016.08.24
Mediator 패턴  (0) 2016.08.22
Decorator 패턴  (0) 2016.08.17
[디자인패턴] 2. Adapter 패턴 - 바꿔서 재이용하기  (0) 2013.02.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함