싱글톤 패턴 Singleton Pattern
클래스내에서 오직 하나의 객체만 생성하도록 제한하는 소프트웨어 설계기법이다.
때문에 싱글톤 패턴은 전체 시스템 내에서 정확히 하나의 객체만 필요할 때 유용하다.
특징 Characteristics
- 클래스의 생성객체는 오직 하나가 유일하다.
- 새로운 생성자 호출시 최초 생성된 객체를 리턴한다.
- 어디서나 동일한 객체로 접근할 수 있어야한다.
구현 Implementaion
특징을 토대로 다양한 방법으로 싱글톤 패턴을 구현할 수 있는데,
그 중 몇 가지 방법을 코드와 함께 살펴보자.
1) 심각한 초기화 Eager initialization
package practice.iting.tistory.com;
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance(){
return instance;
}
}
위 코드는 기본 원칙을 토대로 작성한 하나의 골격이라 할 수 있다.
static으로 선언함으로써 클래스파일이 JVM에 로드될 때 곧장 객체를 생성하게 하는 구조다.
이는 객체를 생성하고 프로그램이 시작되므로 사용하지도 않는데 공간만 차지할 수 있다.
또, 여러 스레드가 동시에 메소드를 호출할 경우에 둘 이상의 객체가 생성될 수 있다는 문제점이 있다.
이제 이름이 왜 심각한지 알 수 있을 것이다.
2) Static block을 이용한 방법
앞서 언급한 static 키워드의 특성을 활용한 방법이다.
package practice.iting.tistory.com;
public class StaticBlockSingleton {
private static StaticBlockSingleton instance;
static{
try{
instance = new StaticBlockSingleton();
}catch(Exception e){
throw new RuntimeException("초기화 중 에러가 발생했습니다 : " + e);
}
}
public static StaticBlockSingleton getInstance(){
return instance;
}
}
표현만 다를뿐, 크게 다를바 없다.
static 블록을 활용했기으므로 폭넓은 초기화 값들을 가져갈 수 있다는 정도가 다른점이 될 것같다.
3) 게으른 초기화 Lazy initialization
게으른 이유는 인스턴스의 생성을 프로그램의 시작 시점에 하는 것이 아니라,
메소드 호출 시점에 생성하기 때문에 붙여졌다.
package practice.iting.tistory.com;
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {}
public static synchronized LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
synchronized는 동기화를 위한 키워드다.
공유 자원을 점유하고 있는 스레드가 볼일 다 볼 수 있도록 다른 스레드의 진입을 막는 역할을 한다.
예컨대, 자리가 한정되어있는 공중화장실에서 문잠그고 볼일 보는 것과 같다.
4) Enum 키워드를 이용한 방법
Enum(enumerated)은 열거형이라고도 불리는 키워드다.
Enum키워드는 상수들의 집합이며, 프로그램 내에서 한번만 실행되는 특징이 있다.
package practice.iting.tistory.com;
public enum EnumWay {
INSTANCE;
}
내부적인 구조는 사실 1번과 동일하다.
테스트
hashCode() 메소드를 통해 같은 객체가 호출되는지 체크해보도록 하자.
package practice.iting.tistory.com;
public class main {
public static void main(String[] args) {
/*보통 클래스*/
System.out.println("[일반 클래스 비교군]");
NormalClass n1 = new NormalClass();
NormalClass n2 = new NormalClass();
System.out.println("- 첫번째 객체의 고유 코드값 : " + n1.hashCode());
System.out.println("- 두번째 객체의 고유 코드값 : " + n2.hashCode());
System.out.print("- 코드 차이값 : " + (n1.hashCode() - n2.hashCode()) + "\n\n");
/* 싱글톤 패턴 테스트 */
System.out.println("[싱글톤 패턴]");
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println("- 첫번째 객체의 고유 코드값 : " + s1.hashCode());
System.out.println("- 두번째 객체의 고유 코드값 : " + s2.hashCode());
System.out.print("- 코드 차이값 : " + (s1.hashCode() - s2.hashCode()) + "\n\n");
/* 스태틱 블락 싱글톤 */
System.out.println("[스태틱 블락 싱글톤 패턴]");
StaticBlockSingleton b1 = StaticBlockSingleton.getInstance();
StaticBlockSingleton b2 = StaticBlockSingleton.getInstance();
System.out.println("- 첫번째 객체의 고유 코드값 : " + b1.hashCode());
System.out.println("- 두번째 객체의 고유 코드값 : " + b2.hashCode());
System.out.print("- 코드 차이값 : " + (b1.hashCode() - b2.hashCode()) + "\n\n");
/* 레이지 싱글톤 */
System.out.println("[레이지 싱글톤 패턴]");
LazySingleton l1 = LazySingleton.getInstance();
LazySingleton l2 = LazySingleton.getInstance();
System.out.println("- 첫번째 객체의 고유 코드값 : " + l1.hashCode());
System.out.println("- 두번째 객체의 고유 코드값 : " + l2.hashCode());
System.out.print("- 코드 차이값 : " + (l1.hashCode() - l2.hashCode()) + "\n\n");
/* 이넘 활용법 */
System.out.println("[이넘 활용법]");
int e1 = EnumWay.INSTANCE.hashCode();
int e2 = EnumWay.INSTANCE.hashCode();
System.out.println("- 첫번째 객체의 고유 코드값 : " + e1);
System.out.println("- 두번째 객체의 고유 코드값 : " + e2);
System.out.print("- 코드 차이값 : " + (e1 - e2) + "\n\n");
}
}
나름 보기 쉽게 정리해봤다.
결과
코드 차이값이 0이라는 의미는 같은 인스턴트를 호출했다는 뜻이 된다.
이로써 싱글톤 패턴 디자인에 성공한 것이다.
그러므로 끝.
참고자료
'IT > JAVA' 카테고리의 다른 글
오버로딩(Overloading)과 오버라이딩(Overriding) in JAVA (0) | 2016.05.26 |
---|---|
[통합 개발 환경] 자바(java) :: 이클립스 및 JDK 설치하기 (0) | 2016.05.02 |
자바가상머신(JVM; Java Virtual Machine)의 구조와 작업 수행 절차 (0) | 2016.04.26 |
[디자인 패턴] 디자인패턴(Design Pattern)의 개념과 종류 (0) | 2016.04.25 |
소켓프로그래밍(Socket Programming) in JAVA :: 개념 및 에코서버 예제 (0) | 2016.04.23 |