[디자인패턴 with C++] Factory Pattern (팩토리 메서드)

Jin Hur·2022년 5월 8일
0
post-custom-banner

reference: "모던 C++ 디자인패턴" / 드미트리 네스터룩

직교 좌표계의 좌표 정보를 저장할 구조체이다.

class Point {
private:
	float x, y;

public:
	Point(const float x, const float y)
		: x{ x }, y{y}
	{}
};

여기에 만약 극좌표계로 좌표값을 저장하는 생성자가 오버로딩된다면 다음과 같다.

Point(const float r, const float theta) 
	: x{r*cos(theta)}, y{r*sin(theta)}
{}

문제는 이런 식으로 매개변수 형태가 같은 생성자를 추가하면 컴파일 에러가 뜬다.

이를 위해 좌표계 종류를 구분하는 enum 타입을 파라미터 값에 추가할 수 있다.

enum class PointType {
	cartesian,
	polar
};

class Point {
	...
    
public:

	Point(float a, float b, PointType type = PointType::cartesian) {
		if (type == PointType::cartesian) {
			x = a;
			y = b;
		}
		else {	// (type == PointType::polar)
			x = a * cos(b);
			y = a * sin(b);
		}
	}
    
};

오버로딩에 대한 컴파일 에러는 해결되었지만, 매개변수 명이 (x, y)에서 (a, b)로 변경되었다. 이는 중립적인 이름을 써야하는 부분에 있어 어쩔 수 없는 선택이긴 하지만 생성자의 사용법을 직관적으로 표현하는데 있어 실패한 것이다.

직교 좌표계의 경우 (x, y), 극좌표계의 경우 (r, theta)라고 매개변수 명을 지정한다면 직관적일 수 있을 것이다. 이러한 문제를 팩토리 메서드로 개선할 수 있다.


팩토리 메서드

생성자 자체를 클라이언트에서 호출하지 않게 하고(protected로 생성자를 숨김), 종류에 맞는 Point 객체를 리턴하는 함수를 호출하게 하는 방법이 있다. 이를 위해선 객체를 리턴하는 생성 함수를 static으로 선언하여야 한다.

class Point {
private:
	float x, y;

protected:
	Point(const float x, const float y) 
		: x{ x }, y{ y }
	{}

public:
	// 직교 좌표점을 전달하여 객체 생성
	static Point NewCartesian(float x, float y) {
		return { x, y };	// 생성자 호출 (유니폼 초기화) 
	}

	// 극 좌표점을 전달하여 객체 생성
	static Point NewPolar(float r, float theta) {
		return { r * cos(theta), r * sin(theta) };
	}
};

바로 이 static 메서드들을 팩토리 메서드하고 부른다. 함수의 이름과 좌표 매개변수의 이름들을 통해 그 의미가 무엇인지, 어떤 값이 인자로 주어져야 하는지 명료해졌다.

post-custom-banner

0개의 댓글