Pattern/C++

[C++] 템플릿 메소드 패턴 (Template method pattern)

dpswlsldj 2021. 3. 21. 02:14
728x90
동작 상의 알고리즘의 프로그램 뼈대를 정의하는 행위 디자인 패턴이다. 알고리즘의 구조를 변경하지 않고 알고리즘의 특정 단계들을 다시 정의할 수 있게 해준다.

- https://ko.wikipedia.org/wiki/%ED%85%9C%ED%94%8C%EB%A6%BF_%EB%A9%94%EC%86%8C%EB%93%9C_%ED%8C%A8%ED%84%B4

 

https://commons.wikimedia.org/wiki/File:W3sDesign_Template_Method_Design_Pattern_UML.jpg

 

동작 상 흐름의 뼈대가 되는 부분은 변하지 않게 정의하고, 변하는 부분만 파생 클래스에서 재정의할 수 있도록 만든 패턴입니다.

 

부모 클래스에서는 뼈대가 되는 부분은 private이나 protected로 정의하여 외부에서 건들지 못하게 하고, 변해야 하는 부분은 public으로 정의하여 파생 클래스에서 재정의할 수 있도록 합니다.

 

이런 동작을 통해 코드의 중복을 최대한 피하여 재사용할 수 있습니다.

 

 

아래 소스에서 각각의 파생 클래스에서 printName() 을 호출하면 부모 클래스의 printName()이 호출되고 그 내부의 printNameImpl() 은 파생 클래스에서 재정의가 되어있으므로 파생 클래스의 것으로 호출합니다.

 

AirplaneRecord 클래스의 경우 printNameImpl()을 재정의하지 않았으므로 부모 클래스에서 구현한 것을 실행합니다.

#include <iostream>

using namespace std;

class Record
{
protected:
	virtual void printNameImpl() {
		cout << "print name" << endl;
	}
public:
	virtual Record* Clone() = 0;
	virtual string getName() = 0;
	virtual void printName() final {
		cout << "*** print start ***" << endl;
		printNameImpl();
		cout << "*** print end ***" << endl;
	}
};

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);
	}

	void printNameImpl() override {
		cout << "print name - car" << endl;
	}
};

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);
	}

	void printNameImpl() override {
		cout << "print name - bike" << endl;
	}

};

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()
{
	CarRecord* carRecord = new CarRecord("Car001");
	BikeRecord* bikeRecord = new BikeRecord("Bike001");
	AirplaneRecord* airplaneRecord = new AirplaneRecord("Airplane001");
    
	carRecord->printName();
	bikeRecord->printName();
	airplaneRecord->printName();
}

실행결과

*** print start ***
print name - car
*** print end ***
*** print start ***
print name - bike
*** print end ***
*** print start ***
print name
*** print end ***

Reference

  - ko.wikipedia.org/wiki/%ED%85%9C%ED%94%8C%EB%A6%BF_%EB%A9%94%EC%86%8C%EB%93%9C_%ED%8C%A8%ED%84%B4