본문 바로가기
Engineer/물리엔진

[감 익혀보기] Singleton Design Pattern with C++

by _제이빈_ 2022. 4. 1.


원문

싱글톤 패턴은 한 가지 클래스에 대해 한 가지 인스턴스만 보장하는 방법이다. 즉, 클래스를 전역변수와 비슷한 느낌으로 사용할 수 있다. 그러면 바로 의문이 드는 것이, 어떻게 한번 이상의 인스턴스화를 막을 수 있냐는 것이다! 한번 배워보도록 하자.

MyObject *myObject = new MyObject();


일반적인 클래스의 경우 위와 같이 새로운 인스턴스를 생성할 수 있다. Public 클래스라면 원하는 만큼 인스턴스를 만들수 있다. 그런데 만약 Public이 선언되지 않은 함수라면 어떨까? 아래와 같이 생성자가 protected로 되어 있으면 말이다.

class SingletonPattern{

private:

protected:

	SingletonPattern();

public:

}


이런 상태라면 인스턴스화 자체가 안된다. 인스턴스화를 하려면 인스턴스가 이미 존재해야하는 패러독스에 빠진다.. ㄸ

한가지만 더 실험해 보자, 만약에 public에다가 static으로 인스턴스를 생성하는 맴버변수를 하나 생성해놨다면 어떨까..? 아래와 같이 말이다.


// SingletonPatternExample.h
class SingletonPattern{

private:

protected:

	SingletonPattern();

public:

	static SingletonPattern* instance;

	static SingletonPattern* sharedInstance();

};


// SingletonPatternExample.cpp

#include “SingletonPatternExample.h”

SingletonPattern* SingletonPattern::sharedInstance(){

	if (instance==0){
		instance=new SingletonPattern();
	}

	return instance;

}


이렇게 한다면 이 클래스가 인스턴스화가 가능할까? 그렇다. 다음과 같이 할 수 있다.


SingletonPattern *mySinglton=SingletonPattern::sharedInstance();


그러니까 이 인스턴스가 널포인터면 protected constructor로 맴버함수 내에서 인스턴스화를 시킨 후 포인터를 뱉어주는거고, 만약에 널포인터가 아니면, 원래 참조값 넘겨주게 된다.


구현


그럼 이제, 실제 구현된 싱글톤 패턴을 통해서 감 좀 잡아보자.

// SingletonPattern.h file

class SingletonPattern{

private:

    //1. private 변수

    int i;

protected:

    //2. 생성자
    SingletonPattern():i(0){};

    //3. 소멸자
    ~SingletonPattern(){};

public:

    //4. static instance for class singleton

    static SingletonPattern* instance;

    //5. shared instance for the singleton

    static SingletonPattern* sharedInstance();

    //6. set the value of i
    void setValue(int uValue);

    //7. get the value of i
    int getValue();
};


라인 2에 생성자가 존재하고, 이게 직접적으로 사용되는 때는 라인 4와 라인 5에서이다. sharedInstance();를 사용하면 어디서든지 이 static 클래스에 접근할 수 있을 것이다.

구현부는 아래와 같다.

// SingletonPattern.c file

#include "SingletonPattern.h"
SingletonPattern* SingletonPattern::instance=0;

SingletonPattern* SingletonPattern::sharedInstance(){

    if (instance==0) {
        instance=new SingletonPattern();
    }

    return instance;

}

void SingletonPattern::setValue(int uValue){

    i=uValue;
}

int SingletonPattern::getValue(){
    return i;
}


여기서 set / get 함수가 지리는 포인트인데, 아래와 같이 어느 곳에서든 이 글로벌 클래스(?)에 접근할 수 있는 것이다!

SingletonPattern *singleton=SingletonPattern::sharedInstance();

singleton->setValue(5);

in myValue = singleton->getValue();


어느 곳에서든지 값을 변경할 수 있고 어디서든지 값을 읽어올 수 있다.

더 깊게 공부하고 싶다면 알아보려면 Head Fisrt-Design Pattern 책을 보면 도움이 될 것이다.

반응형

댓글