가장 쉬운 싱글턴 패턴부터 하겠습니다.
싱글턴(Singleton)
<의도>
클래스의 인스턴스를 오직 하나만 만들고 그것에 쉽게 접근을
하고 싶다.
<동기>
가끔 클래스의 인스턴스가 오직 하나만 존재해야 경우가 있을 것 입니다. DirectX의 DirectDraw, DirectSound등의 컴포넌트들이 이런 경우에 해당 하겠지요. 특히나 이런 컴포넌트 들은 자주
사용하기 때문에 컴포넌트 변수를 쉽게 얻어올 수 있어야 할 것 입니다.
그래서 대부분의 라이브러리를 보면
LPDIRECTDRAW7 g_pDDraw;
이런 식으로 전역 변수를 만드는 경우가 많습니다. 전역 변수로 만들면 사용하기 편하기 때문이지요. 그러나 역시 클래스화를 하는 것이 사용하기에 더 편하므로 클래스화를 할 것입니다.
class cDirectDraw
{
...
LPDIRECTDRAW7 m_pDDraw;
public:
cDirectDraw();
~cDirectDraw();
void Create();
void Draw();
void Flip();
...
};
이런 식으로 할 것입니다. 이것도 편하긴 하지만 객체의 인스턴스를 여러개 만들려고 할 경우에
어떻게 동작할지 알 수 없습니다. 뭐~ 이 글을 보시는 분들은 DirectX를 잘 알고 계실테니 위
클래스의 인스턴스를 두개 이상 만들려고 하시는 분은 없겠지만,
여러 분이 잘 모르는 분야의 클래스를 만들 경우에는 그런 실수를 할 수도 있습니다.
또는 프로젝트가 커지고 복잡해져도 그런 실수를 하기 쉽겠지요.
클래스 옆에다 주석으로 '인스턴스를 두 개 이상 만들면 안 됨! !' 이라고 써놓는다고 해도 그런
실수를 할 가능성은 여전히 존재합니다. 게다가 기억하고 있어야 할 주의사항이 많다면 머리속을
혼란하게 만들죠.
이것들에 대한 좋은 해결책이 바로 이 싱글턴 패턴입니다. 이패턴은 전역변수만큼 사용하기
쉽게 해주고, 절대 하나 이상의 인스턴스를 만들지 못하도록 막아줍니다.
<소스>
class cDirectDraw
{
...
LPDIRECTDRAW7 m_pDDraw;
public:
//인스턴스를 얻어오는 함수
static cDirectDraw & GetInstance();
void Create();
void Draw();
void Flip();
~cDirectDraw();
...
protected:
//인스턴스 생성을 막는다
cDirectDraw();
};
cDirectDraw & cDirectDraw::GetInstance()
{
//static이므로 오직 하나만 생성
static cDirectDraw DDraw;
return DDraw;
}
<사용예>
cDirectDraw & DDraw = cDirectDraw::GetInstance();
DDraw.Draw();
DDraw.Flip();
//또는
cDirectDraw::GetInstance().Draw();
//이런 식으로 사용해도 됩니다.
여기서 눈여겨 봐야 할 부분은 생성자와 GetInstance함수 입니다.
생성자는 외부에서 cDirectDraw의 인스턴스를 만들지 못하게 하기 위해서 protected에넣었습니다.
만약 cDirectDraw의 인스턴스를 만들려고 하면 컴파일 에러를 일으킬 것입니다.
그리고 GetInstance함수는 아무때나 사용할 수 있도록 static 함수로 만들었습니다.
GetInstance함수의 정의 부분에서는 cDirectDraw의 인스턴스를 static으로 만들었기 때문에 함수가
계속 호출되도 오직 하나의 인스턴스만 만들게 됩니다. 게다가 함수가 처음 호출되는 때에 static
변수를 생성하기 때문에 GetInstance함수를 호출하지 않으면 cDirectDraw클래스 인스턴스도
만들지 않습니다.
p.s 사실 위에서 구현한 방식은 상속을 할 경우 문제가 발생합니다. 상속을 할 수 있게 하기 위한
좀 더 복잡한 구현이 디자인 패턴 책에 있으니 원하시는 분은 그것을 참고하세요. 아니면 메일을
주세요~. 그러면 따로 강좌를 써드리겠습니다.