아이티-잉

공부하며 정리하는 IT블로그

Today   Total  
2023년! 복 많이 받으세요

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

2016. 4. 24. 15:20

싱글톤 패턴 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이라는 의미는 같은 인스턴트를 호출했다는 뜻이 된다.

이로써 싱글톤 패턴 디자인에 성공한 것이다.

 

 

 

그러므로 끝.

 

 

 

참고자료

 

위키 / 생활코딩

블로그 - 서토리 / 끙애내꼬 / 파워풀프로그래밍