Thinking Different







Abstract Factory 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//------------------------------------------------------------------
// ProductA 인터페이스 클래스
class AbstractProductA
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// ProductB 인터페이스 클래스
class AbstractProductB
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// ConcreteProductA1 클래스
class ConcreteProductA1 : public AbstractProductA
{
public:
    void print() override { cout << "ConcreteProductA1" << endl; }
};
 
//------------------------------------------------------------------
// ConcreteProductA2 클래스
class ConcreteProductA2 : public AbstractProductA
{
public:
    void print() override { cout << "ConcreteProductA2" << endl; }
};
 
//------------------------------------------------------------------
// ConcreteProductB1 클래스
class ConcreteProductB1 : public AbstractProductB
{
public:
    void print() override { cout << "ConcreteProductB1" << endl; }
};
 
//------------------------------------------------------------------
// ConcreteProductB2 클래스
class ConcreteProductB2 : public AbstractProductB
{
public:
    void print() override { cout << "ConcreteProductB2" << endl; }
};
 
//------------------------------------------------------------------
// Factory 인터페이스 클래스
class AbstractFactory
{
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
};
 
//------------------------------------------------------------------
// ConcreteFactory1 클래스
class ConcreteFactory1 : public AbstractFactory
{
public:
    AbstractProductA* createProductA() override { return new ConcreteProductA1; }
    AbstractProductB* createProductB() override { return new ConcreteProductB1; }
};
 
//------------------------------------------------------------------
// ConcreteFactory2 클래스
class ConcreteFactory2 : public AbstractFactory
{
public:
    AbstractProductA* createProductA() override { return new ConcreteProductA2; }
    AbstractProductB* createProductB() override { return new ConcreteProductB2; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    ConcreteFactory1 pFactory1;
    ConcreteFactory2 pFactory2;
 
    AbstractProductA* pA1 = pFactory1.createProductA();
    pA1->print();
 
    AbstractProductB* pB1 = pFactory1.createProductB();
    pB1->print();
 
    AbstractProductA* pA2 = pFactory2.createProductA();
    pA2->print();
 
    AbstractProductB* pB2 = pFactory2.createProductB();
    pB2->print();
 
    delete pA1;
    delete pB1;
    delete pA2;
    delete pB2;
 
    return 0;
}




예제를 통한 추상 팩토리 패턴(Abstract Factory Pattern) 알아보기


예제) UI 구성 예제


UI를 구성하는 버튼, 스크롤이 있고, 그 객체를 전담 생성해주는 추상 팩토리가 있다. 추상 팩토리 인터페이스에서는 서로 다른 클래스들을 생성할 수 있도록 각각의 클래스 생성 메소드를 제공하고, 실제 생성 코드는 하위에서 생성하도록 한다.


예제코드)

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
    void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
    void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
    void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
    void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 팩토리 인터페이스
class IUIFactory
{
public:
    virtual IButton* createButton() = 0;
    virtual IScroll* createScroll() = 0;
};
 
//------------------------------------------------------------------
// 사각형 팩토리 클래스
class CUIFactory_Rectangle : public IUIFactory
{
public:
    IButton* createButton() override { return new CButtonRectangle; }
    IScroll* createScroll() override { return new CScrollRectangle; }
};
 
//------------------------------------------------------------------
// 동그라미 팩토리 클래스
class CUIFactory_Circle : public IUIFactory
{
public:
    IButton* createButton() override { return new CButtonCircle; }
    IScroll* createScroll() override { return new CScrollCircle; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    CUIFactory_Rectangle mRectangleFactory;
    
    IButton* pRectangleButton = mRectangleFactory.createButton();
    IScroll* pRectangleScroll = mRectangleFactory.createScroll();
    
    pRectangleButton->print();
    pRectangleScroll->print();
 
    delete pRectangleButton;
    delete pRectangleScroll;
 
    return 0;
}


예제 결과)






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

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



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




확장 설계 소스 코드)

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
    virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
    void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
    void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
    void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
    void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 추상 팩토리 템플릿 인터페이스 (템플릿 메소드 패턴 적용)
template<typename T>
class AbstractFactory
{
public:
    T* Create() { return createProduct(); }
 
protected:
    virtual T* createProduct() = 0;
};
 
//------------------------------------------------------------------
// 팩토리 템플릿 클래스 (세부 객체 생성 전담)
template<typename T1, typename T2>
class ConcreteFactory : public AbstractFactory<T1>
{
private:
    T1* createProduct() override { return new T2; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    ConcreteFactory<IButton, CButtonCircle> mCircleFactory;
    ConcreteFactory<IScroll, CScrollRectangle> mRectangleFactory;
 
    IButton* pCircleButton = mCircleFactory.Create();
    IScroll* pRectangleScroll = mRectangleFactory.Create();
 
    pCircleButton->print();
    pRectangleScroll->print();
 
    delete pCircleButton;
    delete pRectangleScroll;
 
    return 0;
}


확장 설계 예제 결과)