본문 바로가기
Programming/c++ Design Pattern

[c++ Design Pattern] Template Method

by 드가보자 2023. 11. 29.

Template Pattern (템플릿 메서드)

 

템플릿 메서드 패턴은 어떤 알고리즘의 구조를 정의하고, 이 알고리즘의 특정 단계를 파생 클래스에서 구현할 수 있도록 하는 패턴입니다.

이렇게 하면은 추상 클래스 (interface 역할) 하는 부분은 수정하지 않아도, 새로운 파생 클래스에서 특정 virtual 함수 부분만 정의하면 문제 없이 프로그램이 동작하게 되는 이점이 있습니당.

 

우선 예제 코드를 살펴보면은,

#include <iostream>
#include <string>
#include <conio.h>

class Edit
{
	std::string data;
public:
	std::string get_data()
	{
		data.clear();

		while (1)
		{
			char c = _getch(); 

			if (c == 13) break;  

			if (isdigit(c))
			{
				data.push_back(c);
				std::cout << c;
			}
		}
		std::cout << '\n';
		return data;
	}
};


int main()
{
	Edit e;
	while (1)
	{
		std::cout << e.get_data() << std::endl;
	}
}

 

키보드 입력을 받아서, string data를 만들고 그것을 출력하는 Editor를 하나 만들어 보겠다.

우선 conio header 파일에 대해서 알아봐야 한다.

[Conio]

Conio -> Console input / output의 약자이다.

주로 콘솔 창에서 간단한 텍스트 기반의 입출력을 처리하기 위해 사용한다. 

여기서 사용하는 함수는 getch함수인데, goto(x,y) , cprintf 등 다양한 함수가 있으니 찾아보는 것을 추천한다.

1. getch() -> 키보드에서 한 문자를 입력받는 함수, 키를 누를 때까지 프로그램이 대기한다. 

 

string data를 멤버 변수로 가지는 class에서, get_data 함수를 실행하면 

멤버 변수 data를 clear하고, getch함수로 문자열 하나를 입력받고, 입력 받은 값이 숫자인지 확인 -> isdigit() 

isdigit(c) -> c가 숫자라면 isdigit은 0이 아닌 값을 반환하고, 숫자가 아니라면 0을 반환한다.

숫자일 경우에 data에 추가한다. 그리고 Enter 입력을 받으면 loop를 탈출 후 string data를 return 한다.

 

main 함수에서는 이 과정을 무한 반복하는데, 입력받은 숫자를 계속해서 출력해주는 역할을 한다. 

 

다음과 같이 입력하는 숫자를 그대로 출력하는 역할을 한다.

 

이번에는 5자리의 숫자 외에 다른 숫자들은 입력 받지 못하게 validation 과정을 추가한 코드를 보겠다.

 

#include <iostream>
#include <string>
#include <conio.h>

class Edit
{
	std::string data;
protected:
	virtual bool validate(const std::string& data, char c)
	{
		return true;
	}

	virtual bool is_complete(const std::string& data)
	{
		return true;
	}

public:
	std::string get_data()
	{
		data.clear();

		while (1)
		{
			char c = _getch();

			if (c == 13 && is_complete(data)) break;
            
			if (validate(data, c))	
			{
				data.push_back(c);
				std::cout << c;
			}
		}
		std::cout << '\n';
		return data;
	}
};
class NumEdit : public Edit
{
	int limit;
public:
	NumEdit(int limit = -1) : limit(limit) {}

	bool validate(const std::string& data, char c) override
	{
		return isdigit(c) && (limit == -1 || data.size() < limit);
	}

	bool is_complete(const std::string& data) override
	{
		return limit == -1 || data.size() == limit;
	}
};

int main()
{
	//	Edit e;			// 모든 값을 입력 가능
	NumEdit e(5);	// 5자리 이하의 숫자만 입력 가능

	while (1)
	{
		std::cout << e.get_data() << std::endl;
	}
}

 

class Edit에서 get_data하는 부분에 추가된 것이 있다.

validate 과정을 거쳐서 string에 char를 push_back 해주고, Enter입력과 is_complete 이 같이 이루어져야지 loop 문을 탈출하게 된다. 

여기서 is_completed 함수와 validate 함수는 protected 접근 제어로 설정해주고, virtual로 만들어 놓는다.

 

그리고 Edit을 상속 받는 숫자 편집 전용 NumEdit class를 만든다. 여기서는 기반 클래스에서 virtual로 정의된 함수들을 재정의 해준다.

 

자리수 limit을 5로 설정하고, validate 함수는 자리수가 5미만인지 체크하고, 5보다 작다면 추가적인 입력을 받을 수 있게 한다. is_completed 함수는 가지고 있는 data의 자리수가 5인지 체크하는 역할을 한다. 

 

만약 새로운 특수문자를 편집하는 Editor가 나왔다고 하면, validate 부분과 is_complete 부분만 Desgin 해주면 

추상 클래스 (기반 클래스)는 수정 할 필요가 없게 되는 것이다 => 유지 보수 용이

 

 

 

 

'Programming > c++ Design Pattern' 카테고리의 다른 글

[C++ Design Pattern] Composite  (1) 2023.11.29
[C++ Design Pattern] Strategy Pattern  (0) 2023.11.29
[C++] OCP Code 예제  (1) 2023.11.29
[C++] 추상 클래스  (0) 2023.11.29
[C++] 가상 함수  (1) 2023.11.28