Pattern/C++

[C++] 프로토타입 패턴 (Prototype pattern)

dpswlsldj 2021. 3. 21. 01:30
728x90

객체를 복사하여 새로운 객체를 만들 때 사용하는 패턴입니다.

 

객체를 새로 생성할 때, 객체의 타입을 프로토타입인 인스턴스로부터 결정되도록 하며, 인스턴스는 새 객체를 만들기 위해 자신을 복제(clone)하는 패턴.

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4

 

https://commons.wikimedia.org/wiki/File:Prototype_Pattern_ZP.svg

객체를 생성할 때 런타임 시 new를 사용하지 않고 clone하기 때문에 내부의 변수(속성, attribute)들이 그대로 복제됩니다. new를 사용하면 내부의 변수들은 초기화된 상태로 새 객체가 생성됩니다.

 

이를 위해 부모클래스에서 virtual 함수로 Clone()을 정의해 주어야 합니다.

#include <iostream>

using namespace std;

class Record
{
public:
	virtual Record* Clone() = 0;
	virtual string getName() = 0;
};

class CarRecord : public Record
{
private:
	string name;
public:
	CarRecord(string name)	{
		this->name = name;
	}
	
	CarRecord(CarRecord& carRecord) {
		this->name = carRecord.name;
	}

	string getName() override {
		return this->name;
	}

	Record* Clone() override {
		return new CarRecord(*this);
	}
};

class BikeRecord : public Record
{
private:
	string name;
public:
	BikeRecord(string name)	{
		this->name = name;
	}

	BikeRecord(BikeRecord& bikeRecord) {
		this->name = bikeRecord.name;
	}

	string getName() override {
		return this->name;
	}

	Record* Clone() override {
		return new BikeRecord(*this);
	}
};

int main()
{
	CarRecord* carRecord = new CarRecord("Car001");
	BikeRecord* bikeRecord = new BikeRecord("Bike001");
	
	Record* aRecord = carRecord->Clone();
	Record* bRecord = bikeRecord->Clone();

	cout << carRecord->getName() << endl;
	cout << bikeRecord->getName() << endl;

	cout << aRecord->getName() << endl;
	cout << bRecord->getName() << endl;
}

위 코드의 결과는 아래와 같습니다.

 

객체들이 복사된 것을 볼 수 있습니다.

Car001
Bike001
Car001
Bike001

 

이렇게 함으로써 얻을 수 있는 장점은 새로운 객체가 추가되어도 기존 소스들은 변경되지 않고 Clone() 하나로 또 다른 객체의 복사를 수행할 수 있다는 것입니다. (다형성)

 

위의 소스에 AirplaneRecord 클래스가 추가되어도 해당 객체를 복사하는 동작은 동일하게 Clone() 으로 할 수 있게 됩니다.

class AirplaneRecord : public Record
{
private:
	string name;
public:
	AirplaneRecord(string name) {
		this->name = name;
	}

	AirplaneRecord(AirplaneRecord& airplaneRecord) {
		this->name = airplaneRecord.name;
	}

	string getName() override {
		return this->name;
	}

	Record* Clone() override {
		return new AirplaneRecord(*this);
	}
};

int main()
{
	AirplaneRecord* airplaneRecord = new AirplaneRecord("Airplane001");
	Record* cRecord = airplaneRecord->Clone();

	cout << airplaneRecord->getName() << endl;
	cout << cRecord->getName() << endl;
}

 

Reference

  - ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4