해석자 패턴 (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; } |
예제 결과)
'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 |