Pattern : Singleton C/C++ 마을



싱글톤 패턴은 프로그래머가 해당 객체가 단 하나만 존재하도록 원할 때 사용할 수 있는 패턴이다.

이 패턴을 사용함으로써 해당 객체의 인스턴스는 프로그램상에 단 하나만 존재하는 것이 보장된다.


01: // SingleTon.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
02: //
03:
04: #include "stdafx.h"
05: #include <iostream>
06:
07: class KSingleTon
08: {
09: private:
10: static KSingleTon* Inst;
11: //static void destory (void ) { delete KSingleTon::Inst; }
12: ~KSingleTon() { std::cout << "Delete KSingleTon" << std::endl; };
13:
14: public:
15:
16: KSingleTon() {};
17:
18: static KSingleTon* GetInstance (void)
19: {
20: if ( KSingleTon::Inst == 0 )
21: {
22: KSingleTon::Inst = new KSingleTon();
23: //atexit(destory);
24: }
25:
26: return KSingleTon::Inst;
27: }
28:
29: void Use() { std::cout << "Use KSingleton" << std::endl; }
30: };
31:
32: KSingleTon* KSingleTon::Inst;
33:
34: int _tmain(int argc, _TCHAR* argv[])
35: {
36: KSingleTon* Single = KSingleTon::GetInstance();
37:
38: Single->Use();
39:
40:
41: return 0;
42: }
43:

정적 변수(객체)는 프로그램 종료시에 메모리에서 제거되는 것이 보장되므로 우리는 따로 이 싱글턴 인스턴스를 Delete 할 필요 없다. 하지만 이 객체가 시스템의 자원을 사용하고, 프로그램이 종료될때에 객체가 시스템 리소스를 반납할 필요가 있다면 어떻게 해야할까? 

위 코드에서 소멸자에 Delete KSingleTon 이란 문구가 출력되도록 설정 되어 있지만 소멸자는 호출 되지 않는다. 따라서 atexit 함수를 이용해 객체를 Delete 하는 함수를 등록하거나 SingletonDestoryer 와 같은 프렌즈 클래스를 통해서 싱글턴 객체를 제거 할 수 있다. 

위의 코드에서 주석을 제거하고 실행해 보면 atexit 함수를 통해 등록된 destory 함수가 호출되고, 이 함수가 객체를 제거하므로 소멸자가 성공적으로 호출됨을 알 수 있다. 이러한 과정이 귀찮다면, 지역 정적 변수를 이용하면 된다. 

지역 정적 변수는 전역 정적 변수와는 다르게 사용될때만 생성되며, 지역변수 이므로 프로그램 종료시 소멸자가 호출되는 것을 보장한다. 아래의 코드를 보자.



01: // SingleTon.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
02: //
03:
04: #include "stdafx.h"
05: #include <iostream>
06:
07: class KSingleTon
08: {
09: private:
10: ~KSingleTon() { std::cout << "Delete KSingleTon" << std::endl; };
11: static KSingleTon* Inst;
12:
13: public:
14:
15: KSingleTon() {};
16:
17: static KSingleTon* GetInstance (void)
18: {
19: if ( !KSingleTon::Inst )
20: {
21: static KSingleTon Single;
22: Inst = &Single;
23: }
24:
25: return KSingleTon::Inst;
26: }
27:
28: void Use() { std::cout << "Use KSingleton" << std::endl; }
29: };
30:
31: KSingleTon* KSingleTon::Inst;
32:
33: int _tmain(int argc, _TCHAR* argv[])
34: {
35: KSingleTon* Single = KSingleTon::GetInstance();
36:
37: Single->Use();
38:
39:
40: return 0;
41: }
42:

하지만 이러한 구현도 문제점이 존재한다. C++ 에서는 객체의 소멸 순서가 정해져 있지 않기 때문에 다른 객체의 소멸자에서 이 Singleton 객체를 사용하려 할때, 이미 제거되었다면 오류가 발생하게 된다. 이러한 문제를 해결하기 위해서 스콧 마이어스는 자신의 책에서 'Phoenix Singleton' 이란 개념을 소개했는데, 자세한 내용은 다음의 링크를 참고하라.


About Phoenix Singleton -  http://ikpil.com/1277



덧글

댓글 입력 영역


시계

라운드 시계

위키피디아