-
[디자인패턴]싱글턴 패턴(Singleton Pattern)IT, 프로그래밍/Design Patterns 2017. 12. 25. 01:14
싱글턴 패턴(Singleton Pattern) = 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴.
싱글턴 객체는 유일하게 존재 하는 객체입니다. 예를 들면, 레지스트리 설정이라던가, DB 커넥션 객체 등이 여러 개 존재하면 심각한 오류가 발생하거나, 자원이 낭비 될 가능성이 있죠.
(예를 들어서 2개의 설정 객체의 인스턴스를 무작위로 참조 하게 된다면.. )
이런 객체들은 단 하나만 존재하게 해서, 그 객체의 인스턴스만 어디서든 쓸 수 있게 만들어 줘야 합니다.
싱글턴 객체가 이 싱글턴 객체를 어떻게 만들까요?
싱글턴 객체를 만드려면 두 가지의 조건을 만족해야 합니다.
1. 어디서든 접근이 가능하고, 인스턴스를 얻어서 사용할 수 있게 할 것.
2. 객체는 단 하나만이 메모리에 할당 되어 있을 것.
이런 조건들을 살펴 보았을때, 인스턴스를 얻는 getInstance()라는 정적 메소드를 정의 하는 것이 좋아 보입니다. 그래서 이렇게 코드를 작성할 수 있죠.
12345678910111213141516171819public class Singleton{private static Singleton uniqueInstance; // 유일한 변수를 사용하기 위해 정적 변수로 선언private Singleton() {}public static Singleton getInstance() {if(uniqueInstance == null) {uniqueInstance = new Singleton();} //필요할때만 객체를 생성하는 방식. 게으른 인스턴스 생성(lazy instantiation)return uniqueInstance;}}cs 이렇게 되면 변수와 생성자는 private으로 선언되어 있기 때문에 아무도 건드릴 수 없고, 오직 getInstance() 메소드를 통해 이 객체에 접근할 수 있습니다.
이렇게 작성 된 싱글턴 패턴은 단일 스레드 환경에서는 별 문제가 없지만, 다중 스레드 환경에서는 심각한 문제를 초래할 수 있습니다.
스레드는 프로세스와 같이 스케줄링에 의한 문맥교환(context switching)이 발생합니다. 이렇게 되면 2개의 객체가 생성될 수 있습니다.
이 문제를 해결하려면 세 가지의 방법이 있습니다.
1. synchronized , 동기화를 사용한다.
2. 인스턴스를 필요할 때 생성하지 말고, 아예 처음부터 정적 객체로 생성한다.
3. DCL (Double-Checking Locking)을 사용한다.
1. 동기화를 이용한 방법
12345678910111213141516171819public class Singleton{private static Singleton uniqueInstance; // 유일한 변수를 사용하기 위해 정적 변수로 선언private Singleton() {}public static synchronized Singleton getInstance() { // 동기화 처리if(uniqueInstance == null) {uniqueInstance = new Singleton();} //필요할때만 객체를 생성하는 방식. 게으른 인스턴스 생성(lazy instantiation)return uniqueInstance;}}cs --> 이 방법을 사용하면 간단하지만, 객체가 한 번 생성되면 더이상 생성 시킬 필요가 없는데도 불구하고 계속 동기화 처리를 하여 성능 저하가 일어난다는 단점이 있습니다. 약 100배의 속도 저하가 일어납니다.
2. 아예 처음부터 생성하는 방법
123456789101112131415public class Singleton{private static Singleton uniqueInstance = new Singleton(); // 생성과 동시에 초기화private Singleton() {}public static Singleton getInstance() {return uniqueInstance;}}cs --> 이렇게 되면 스레드의 영향을 받지 않고 유일한 객체를 생성할 수 있게 됩니다.
3. DCL 이용하는 방법
1234567891011121314151617181920public class Singleton {private volatile Singleton uniqueInstance;private Singleton() {}public static Singleton getInstance() {if (uniqueInstance == null) {synchronized (Singleton.class) {if (uniqueInstance == null) {uniqueInstance = new Singleton();}}}return uniqueInstance;}}cs --> 이 방식을 사용하면 synchronized만 사용할때 보다 오버헤드를 매우 낮출 수 있으나 자바 1.4 이하 버전에서는 volatile 예약어를 지원하지 않습니다.
'IT, 프로그래밍 > Design Patterns' 카테고리의 다른 글
[디자인패턴] 어뎁터 패턴 (Adapter Pattern) (3) 2019.01.05 [디자인 패턴] 커맨드 패턴 (Command Pattern) (1) 2017.12.25 [디자인패턴] 추상 팩토리 패턴 (Abstract-Factory Pattern) (1) 2017.12.10 [디자인패턴] 팩토리 메소드 패턴 (Factory-Method Pattern) (2) 2017.12.10 [디자인패턴] 데코레이터 패턴 (Decorator Pattern) (4) 2017.10.21