bdfgdfg
[온라인 서버] 네트워크 라이브러리 - Singleton Class 본문
Singleton class
- 많이 사용하는 디자인 패턴 기법으로 오직 하나의 객체만 생성하여 사용하는 클래스를 의미한다.
-> 패턴은 쉽게 말하면 개발자들의 경험을 통한 문제 해결 방법들을 정리하여 이름을 부여한 기법들.
- 이러한 단일체(Singleton)클래스는 어떤 클래스(객체)들을 관리하는 역할로 많이 쓰인다.
-> ex) User를 관리하는 UserManager등등.. 보통 Manager가 붙은 클래스들이 Singleton을 사용한다.
먼저 싱글톤 클래스를 하는데 싱글톤 패턴을 사용하는 모든 단일체 클래스는 이 클래스를 상속받는다.
-> 모든 싱글턴 객체들을 관리한다. 해제할 때는 이 Singleton클래스를 통해 해제.
싱글톤 패턴을 사용하기 쉽게 매크로를 이용해본다.
#define DECLARE_SINGLETON(className)\
public:\
static className* GetInstance();\
virtual void ReleaseInstance();\
private:\
static className* m_pInstance;
#define CREATE_FUNCTION(className, funcName)\
static className* ##funcName()\
{\
return className::GetInstance();\
}
#define IMPLEMENT_SINGLETON(className)\
className* className::m_pInstance = nullptr;\
className* className::GetInstance()\
{\
if(m_pInstance == nullptr)\
m_pInstance = new className();\
return m_pInstance;\
}\
void className::ReleaseInstance()\
{\
if(m_pInstance != nullptr)\
{\
delete m_pInstance;\
m_pInstance = nullptr;\
}\
}
\는 매크로에서 다음 라인을 의미한다.
먼저 DECLARE_SINGLETON 매크로.
이 매크로는 Singleton클래스를 상속받는 단일체 클래스의 내부에 선언되어야 한다.
인자로 상속받는 클래스의 이름을 받으며 이 매크로가 선언되는 클래스는 실제로 단일체 클래스를 만들기 위해 필요한
두개의 함수와 한개의 변수를 선언하게 된다.
-> 두개의 함수 : GetInstance(), ReleaseInstance() (ReleaseInstance는 순수 가상함수를 통해 구현해야 되는 가상함수)
-> 한개의 변수 : m_pInstance (단일체 클래스의 단 하나만 존재하는 객체)
그 다음 CREATE_FUNCTION
외부에서 쉽게 단일체 클래스의 단일 객체에 접근하기 위한 함수.
인자로 단일 객체를 호출하기 위한 호출 함수이름을 넘겨준다. (아무거나 상관없지만 클래스명에 맞추어GetUtilManager등등)
마지막으로 IMPLEMENT_SINGLETON
단일체 클래스의 cpp파일에 선언되는 매크로.
위에서 DECLARE_SINGLETON의 구현부분이다. 인자로는 상속받는 클래스의 이름을 받는다.
이제 싱글톤 클래스를 보자.
#include <list>
class Singleton
{
public:
// 이 클래스를 상속하는 모든 싱글톤 클래스들을 관리한다.
using SINGLETON_LIST = std::list<Singleton*>;
Singleton();
virtual ~Singleton();
public:
virtual void ReleaseInstance() abstract; // = 0으로 구현하는 순수 가상함수와 동일. (해당 클래스는 추상 클래스가 된다.)
static void ReleaseAll();
private:
static SINGLETON_LIST m_listSingleton;
};
#include "Singleton.h"
Singleton::SINGLETON_LIST Singleton::m_listSingleton;
Singleton::Singleton()
{
m_listSingleton.push_back(this);
}
Singleton::~Singleton()
{
SINGLETON_LIST::iterator singletonIter = m_listSingleton.begin();
for (; singletonIter != m_listSingleton.end(); )
{
if ((*singletonIter) == this) // 자기자신 파괴
break;
++singletonIter;
}
m_listSingleton.erase(singletonIter);
}
void Singleton::ReleaseAll()
{
// 처음 원소는 싱글턴 클래스 자기자신이므로. 거꾸로 지운다.
SINGLETON_LIST::reverse_iterator singleIter = m_listSingleton.rbegin();
while (singleIter != m_listSingleton.rend())
{
(*singleIter)->ReleaseInstance();
++singleIter;
}
m_listSingleton.clear();
}
소멸자에선 list에 저장된 Singleton 객체를 제거하는 역할을 하며
ReleaseAll에서는 list가 관리하는 싱글톤 객체들을 모두 해제하는 역할을 한다.
이제 Singleton클래스를 사용하는 예제를 본다.
#pragma once
#include "Singleton.h"
class UtilManager : public Singleton
{
DECLARE_SINGLETON(UtilManager);
public:
int CalcSum(int a, int b) { return a + b; }
};
// 클래스이름은 UtilManager. 함수명은 GetUtilManager로 하였음.
CREATE_FUNCTION(UtilManager, GetUtilManager)
#include "UtilManager.h"
IMPLEMENT_SINGLETON(UtilManager);
위와 같이 싱글턴 클래스들은 매크로를 통해 싱글톤 패턴에서 자주 사용되는 함수와 변수들을 매번 칠 필요없이
간단하게 구현 가능하다.
이제 위의 UtilManager의 단일객체에 접근하여 CaclSum을 사용해보면
int main()
{
std::cout << GetUtilManager()->CalcSum(10, 20);
}
매우 손쉽게 사용가능하다.
'게임프로그래밍 > 서버 책' 카테고리의 다른 글
[온라인 서버] 네트워크 라이브러리 - Thread 클래스 (0) | 2022.01.08 |
---|---|
[온라인 서버] 네트워크 라이브러리 - RingBuffer 클래스 ★ (메모리 풀!) (0) | 2022.01.05 |
[온라인 서버] 네트워크 라이브러리 - Monitor Class (0) | 2022.01.04 |
[온라인 서버] 네트워크 라이브러리(정적,동적) 만들기 (0) | 2022.01.03 |
[온라인 서버] I/O Completion Port(IOCP) 모델 실습 (0) | 2021.12.30 |