Thinking Different







Factory Method Pattern - 팩토리 메서드 패턴


  • 객체를 생성하는 일을 전담하도록 한다
  • 인터페이스를 바탕으로 유연성과 확장성이 뛰어난 코드 제작이 가능하다 (리펙토링에 유리)
  • 인터페이스에서 객체 생성을 요청하지만, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정한다 
  • 이는 곧 템플릿 메소드 패턴(Template Method Pattern)을 활용한 패턴이라고 할 수 있다. 실제로 위 그림에서 오른쪽 Creator와 ConcreteCreator 클래스만 뜯어보면 템플릿 메소드 패턴(Template Method Pattern) 인 것을 확인 할 수 있다




샘플 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//------------------------------------------------------------------
// Product 인터페이스 클래스
class Product
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// Product 상속 클래스
class ConcreteProduct : public Product
{
public:
    void print() override { cout << "ConcreteProduct" << endl; }
};
 
//------------------------------------------------------------------
// Creator 클래스 (구현 인터페이스 클래스)
class Creator
{
public:
    Product* AnOperation() { return FactoryMethod(); }
 
protected:
    virtual Product* FactoryMethod() = 0;
};
 
//------------------------------------------------------------------
// Creator 상속 클래스 (실제 객체 생성 전담)
class ConcreteCreator : public Creator
{
private:
    Product* FactoryMethod() { return new ConcreteProduct; }
};
 
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    ConcreteCreator pCreator;
 
    Product* pProduct = pCreator.AnOperation();
    pProduct->print();
 
    delete pProduct;
 
    return 0;
}




예제를 통한 팩토리 메서드 패턴(Factory Method Pattern) 알아보기



예제) 다양한 유형의 파일 생성 예제



한글과 엑셀 프로그램이 있다고 할때 각각의 프로그램은 각각의 파일들을 생성해야 할 것이다. 그 구체적인 생성부분들은 각각 하위의 클래스내에 문서생성() 함수를 통해서 각각의 문서 생성이 가능하고, 인터페이스에서는 생성() 함수만 제공하여 객체 생성의 유연성을 확장 시킨 구조이다.


예제 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//------------------------------------------------------------------
// 문서 인터페이스 클래스
class 문서_인터페이스
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 한글 문서 클래스
class 문서_한글 : public 문서_인터페이스
{
public:
    void print() override { cout << "한글 파일" << endl; }
};
 
//------------------------------------------------------------------
// 엑셀 문서 클래스
class 문서_엑셀 : public 문서_인터페이스
{
public:
    void print() override { cout << "엑셀 파일" << endl; }
};
 
//------------------------------------------------------------------
// 프로그램 인터페이스 클래스
class 프로그램_인터페이스
{
public:
    문서_인터페이스* 생성() { return 문서생성(); }
 
protected:
    virtual 문서_인터페이스* 문서생성() = 0;
};
 
//------------------------------------------------------------------
// 한글 프로그램 클래스
class 프로그램_한글 : public 프로그램_인터페이스
{
private:
    문서_인터페이스* 문서생성() { return new 문서_한글; }
};
 
//------------------------------------------------------------------
// 엑셀 프로그램 클래스
class 프로그램_엑셀 : public 프로그램_인터페이스
{
private:
    문서_인터페이스* 문서생성() { return new 문서_엑셀; }
};
 
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    프로그램_한글 pHwpCreator;
    프로그램_엑셀 pXlsCreator;
 
    문서_인터페이스* pHwp = pHwpCreator.생성();
    pHwp->print();
 
    문서_인터페이스* pXls = pXlsCreator.생성();
    pXls->print();
 
    delete pXls;
    delete pHwp;
 
    return 0;
}


예제 결과)








템플릿(template)을 활용한 확장 구조 설계

  • 생성해야 할 객체의 종류가 늘어날 때마다 이를 생성하기 위한 클래스를 계속 추가해주어야 하는 문제점 발생!!
  • C++의 Template를 활용하여 객체 생성 클래스를 설계해야 된다



확장 설계 예제) 템플릿을 활용한 확장 설계



다이어그램과 같이 프로그램 인터페이스를 기반으로 하나의 프로그램 템플릿을 제작하고 T 인자로 문서 인터페이스를 전달하도록 하여 간소화 하였다. 소스코드를 보게 되면 쉽게 이해갈 것이라 생각한다. 위의 기본 팩토리 메서드 패턴과 비교하면서 보면 더 쉽게 이해갈 것이다. 결과는 위와 동일하다.



확장 설계 소스 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//------------------------------------------------------------------
// 문서 인터페이스 클래스
class 문서_인터페이스
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 한글 문서 클래스
class 문서_한글 : public 문서_인터페이스
{
public:
    void print() override { cout << "한글 파일" << endl; }
};
 
//------------------------------------------------------------------
// 엑셀 문서 클래스
class 문서_엑셀 : public 문서_인터페이스
{
public:
    void print() override { cout << "엑셀 파일" << endl; }
};
 
//------------------------------------------------------------------
// 프로그램 인터페이스 클래스
class 프로그램_인터페이스
{
public:
    문서_인터페이스* 생성() { return 문서생성(); }
 
protected:
    virtual 문서_인터페이스* 문서생성() = 0;
};
 
//------------------------------------------------------------------
// 프로그램 템플릿 클래스
template<typename T>
class 프로그램_템플릿 : public 프로그램_인터페이스
{
private:
    문서_인터페이스* 문서생성() { return new T; }
};
 
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    프로그램_템플릿<문서_한글> pHwpCreator;
    프로그램_템플릿<문서_엑셀> pXlsCreator;
 
    문서_인터페이스* pHwp = pHwpCreator.생성();
    pHwp->print();
 
    문서_인터페이스* pXls = pXlsCreator.생성();
    pXls->print();
 
    delete pXls;
    delete pHwp;
 
    return 0;
}