해석자 패턴 (Interpreter Pattern)
Gof Design Pattern2014. 2. 8. 15:26
Interpreter Pattern - 해석자 패턴
- 문법 규칙을 클래스화 한 구조로써, 일련의 규칙으로 정의된 언어를 해석하는 패턴이다.
- 문법 규칙이 많아지면 복잡해지고 무거워지기 때문에 그럴땐 차라리 파서/컴파일러 생성기를 쓰는게 좋다.
- 언어분석기 라고 생각하면 되며, 스크립트나 컴파일러 문법 등이 있을수 있다.
- 예로 SQL 구문이나 shell 커멘드 해석기, 통신 프로토콜 등이 있다.
샘플 코드)
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
|
#include <list>
#if _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
//------------------------------------------------------------------
// Context 클래스
class Context
{
public:
Context(const TCHAR* data) : mData(data) {}
public:
const TCHAR* GetData() const { return mData.c_str(); }
private:
tstring mData;
};
//------------------------------------------------------------------
// AbstractExpression 인터페이스
class AbstractExpression
{
public:
virtual void interpret(Context* context) = 0;
};
//------------------------------------------------------------------
// TerminalExpression 상속 클래스
class TerminalExpression : public AbstractExpression
{
public:
void interpret(Context* context) override { cout << "TerminalExpression: " << context->GetData() << endl; }
};
//------------------------------------------------------------------
// NonterminalExpression 상속 클래스
class NonterminalExpression : public AbstractExpression
{
public:
void interpret(Context* context) override { cout << "NonterminalExpression: " << context->GetData() << endl; }
};
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
Context pContext("Programming Context Data");
list<AbstractExpression*> mList;
mList.push_back(new TerminalExpression());
mList.push_back(new NonterminalExpression());
for each (AbstractExpression* pExpression in mList)
{
pExpression->interpret(&pContext);
delete pExpression;
}
mList.clear();
return 0;
}
|
예제를 통한 해석자 패턴(Interpreter Pattern) 알아보기
예제) 문장 규칙 검사기 예제
AndExpression 클래스와 OrExpression을 정의하고 TerminalExpression에서 하나의 문장을 tokenizer하면서 주어진 context 의 명령이 And인지 Or인지 해석해주는 간단한 문장 규칙 검사기 예제이다.
예제 코드)
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
|
#include "stringTokenizer.h"
#include <list>
//------------------------------------------------------------------
// AbstractExpression 인터페이스
class AbstractExpression
{
public:
virtual bool interpret(tstring str) = 0;
};
//------------------------------------------------------------------
// TerminalExpression 상속 클래스
class TerminalExpression : public AbstractExpression
{
public:
TerminalExpression(tstring str) : mliteral(str) {}
public:
bool interpret(tstring str) override
{
stringTokenizer st(str, " ");
while (st.hasMoreTokens())
{
tstring test = st.nextToken();
if (test == mliteral) {
return true;
}
}
return false;
}
private:
tstring mliteral;
};
//------------------------------------------------------------------
// OrExpression 상속 클래스
class OrExpression : public AbstractExpression
{
public:
OrExpression(AbstractExpression* e1, AbstractExpression* e2) : pExpression1(e1), pExpression2(e2) {}
~OrExpression() { if (pExpression1) delete pExpression1; if (pExpression2) delete pExpression2; }
public:
bool interpret(tstring str) override { return pExpression1->interpret(str) || pExpression2->interpret(str); }
private:
AbstractExpression* pExpression1;
AbstractExpression* pExpression2;
};
//------------------------------------------------------------------
// AndExpression 상속 클래스
class AndExpression : public AbstractExpression
{
public:
AndExpression(AbstractExpression* e1, AbstractExpression* e2) : pExpression1(e1), pExpression2(e2) {}
~AndExpression() { if (pExpression1) delete pExpression1; if (pExpression2) delete pExpression2; }
public:
bool interpret(tstring str) override { return pExpression1->interpret(str) && pExpression2->interpret(str); }
private:
AbstractExpression* pExpression1;
AbstractExpression* pExpression2;
};
//------------------------------------------------------------------
// 해석자 문법 생성 함수 : "Owen and (John or (Henry or Mary))"
AbstractExpression* buildInterpreterTree()
{
// Literal
AbstractExpression* terminal1 = new TerminalExpression("John");
AbstractExpression* terminal2 = new TerminalExpression("Henry");
AbstractExpression* terminal3 = new TerminalExpression("Mary");
AbstractExpression* terminal4 = new TerminalExpression("Owen");
// Henry or Mary
AbstractExpression* alternation1 = new OrExpression(terminal1, terminal2);
// John or (Henry or Mary)
AbstractExpression* alternation2 = new OrExpression(terminal3, alternation1);
// Owen and (John or (Henry or Mary))
return new AndExpression(terminal4, alternation2);
}
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
tstring pContext("Mary Owen");
AbstractExpression* pExpression = buildInterpreterTree();
cout << pContext << " is " << pExpression->interpret(pContext) << endl;
delete pExpression;
return 0;
}
|
예제 결과)
헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! - 프로그래밍 언어 | 쿠팡
쿠팡에서 헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! 구매하고 더 많은 혜택을 받으세요! 지금 할인중인 다른 프로그래밍 언어 제품도 바로 쿠팡에서 확인할 수 있습니다.
www.coupang.com
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
'Gof Design Pattern' 카테고리의 다른 글
동기화 패턴 : 범위 잠금 (Synchronization Patterns : Scoped Locking) (0) | 2014.02.21 |
---|---|
풀링 패턴 (Pooling Pattern) (1) | 2014.02.12 |
방문자 패턴 (Visitor Pattern) (0) | 2014.02.04 |
중재자 패턴 (Mediator Pattern) (0) | 2014.02.04 |
반복자 패턴 (Iterator Pattern) (0) | 2014.02.04 |