내배캠/C++

디자인 패턴(Singleton Pattern)

동그래님 2024. 12. 30. 16:20
#include <iostream>
#include <memory>
using namespace std;

class Airplane
{
private:
	static unique_ptr<Airplane> Instance; // 유일하게 객체를 관리할 Instance
	int PositionX, PositionY;

	// 복사 생성자 제한
	Airplane(const Airplane&) = delete;
	// 대입 연산자 제한
	Airplane& operator=(const Airplane&) = delete;

	Airplane() : PositionX(0), PositionY(0)
	{
		cout << "Airplane created at (" << PositionX << ", " << PositionY << ")\n";
	}

public:
	static Airplane* GetInstance() // 객체가 생성 되어있으면 기존의 객체를 반환, 없으면 생성
	{
		if (Instance == nullptr)
		{
			// make_unique 대신 new 사용해서 직접 Airplane 객체 생성
			// make_unique는 템플릿 기반 함수이며, private 생성자에 접근할 때 문제가 발생
			Instance = unique_ptr<Airplane>(new Airplane()); 
		}
		return Instance.get(); // unique_ptr이 관리하는 객체의 포인터를 반환
	}

	void Move(int DeltaX, int DeltaY)
	{
		PositionX += DeltaX;
		PositionY += DeltaY;
		cout << "Airplane moved to (" << PositionX << ", " << PositionY << ")\n";
	}
};

unique_ptr<Airplane> Airplane::Instance = nullptr; //정적 멤버 변수는 클래스 내부에서 메모리를 할당하지 않으므로 클래스 외부에서 초기화

int main()
{
	Airplane* airplane = Airplane::GetInstance();
	airplane->Move(5, 10);

	return 0;
}

 

1. 싱글톤 객체의 필요성

  • 프로그램에서 단 하나의 객체만 필요하거나, 객체의 중복 생성을 방지하려는 경우 싱글턴 패턴을 사용한다.
  • 게임에서 플레이어의 위치나 전역 설정 등등

2. static 변수의 사용

  • Instance를 static으로 선언함으로써, 클래스 차원에서 단일 메모리 공간을 공유한다.
  • 정적 멤버 변수는 클래스가 로드될 때 성성되고, 프로그램이 종료될 때까지 유지된다.

3. 복사와 대입의 제한

  • 복사 생성자와 대입 연산자를 삭제하지 않으면, 객체를 복사할 수 있는데 이는 싱글턴 패턴의 의도를 벗어남으로 복사와 대입을 명시적으로 막아야한다.

4. GetInstance의 역할

  • 객체를 지연 초기화 방식으로 생성한다. 객체가 필요할 때 처음 생성되고, 그 이후에는 기존 객체를 반환한다.

5. make_unique 대신 new 사용

  • make_unique는 템플릿 기반 함수인데, private 생성자에 접근할 때 호출되지 않는 문제가 발생할 수 있다.
  • private  생성자 문제를 우회하기 위해 직접 new로 생성하였다.