싱글턴 패턴은 특정 클래스에 대해 인스턴스가 하나만 생성되고, 어디에서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다. 예를 들면, 레지스트리 설정을 처리하는 객체, 로그 기록용 객체, 프린터나 그래픽 카드 같은 디바이스를 위한 디바이스 드라이버 같은 것을 들 수 있다. 싱글턴 패턴은 정적(static) 클래스 변수와 메소드를 사용하고 접근 제한자(Access Modifier)를 사용하여 구현한다.
다음 코드는 고전적인 싱글턴 패턴입니다.
public class Singleton {
privatestatic Singleton instance; /* 유일한 인스턴를 저장하기 위한 변수 */
/* 생성자를 private로 생성하여 이 클래스에서만 인스턴스를 생성할 수 있음 */
privateSingleton() {};
/* getInstance메소드를 정적 메소드로 선언하여 인스턴스를 생성해 리턴 */
public static Singleton getInstance() {
/* 인스턴스가 없다면 객체를 생성, 있다면 그 객체를 리턴 */
if( instance == null ) { instance = new Singleton(); }
return instance;
}
}
하지만 이런 방식으로 싱글턴 패턴을 구현하면 멀티 쓰레드 환경에서는 객체가 한개 이상 생성 될 수 있다. 멀티 쓰레드 환경에서 객체가 한개 이상 생성되는 것을 방지 하기 위해서 동기화(Synchronized)를 사용한다. 다음 동기화를 사용한 싱글턴 패턴이다.
public class Singleton {
privatestatic Singleton instance;
private Singleton() {};
/* synchronized 키워드를 사용하여 멀티 쓰레드시 동시 실행을 방지 */
public static synchronized Singleton getInstance() {
if( instance == null ) { instance = new Singleton(); }
return instance;
}
}
하지만 동기화방식을 사용하면 불필요한 오버헤드만 증가시키는 단점이 있다. 그렇다면 더 효율적인 방법이 없는가? 해결책은 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버리면 된다.
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {};
public static Singleton getInstance() {
return instance;
}
}
초기화 부분에서 바로 인스턴스를 생성합니다. 그럼 쓰레드를 써도 문제가 없습니다.
또 다른 멀티 쓰레드 문제를 해결하는 방법은 DCL(Double-cheking Locking)을 써서 getInstance()에서 동기화 되는 부분을 줄인다.
public class Singleton {
private volatile static Singleton instance;
private Singleton() {};
public static Singleton getInstance() {
if( instance == null ) { /* 인스턴스가 있는 확인하고, 없으면 동기화 블럭으로 들어감 */
synchronized (Singleton.class) { /* 동기화 */
if( instance == null ) { /* 다시한번 null인지 확인하고 인스턴스를 생성함 */
instance = new Singleton();
}
}
}
return instance;
}
'프로그램 아키텍쳐 > 디자인패턴' 카테고리의 다른 글
어댑터패턴 ( adapter pattern ) (0) | 2009.01.07 |
---|---|
커맨드 패턴 ( Command pattern ) (0) | 2009.01.06 |
팩토리 패턴 ( Factory pattern ) (0) | 2009.01.05 |
데코레이터 패턴 ( Decorator Pattern ) (0) | 2009.01.04 |
자바 내장 옵저버 패턴 (0) | 2009.01.04 |