[Design Pattern] 행동 패턴 10. 인터프리터 (Interpreter)
Table of Contents
인터프리터 패턴 #
- 어떤 언어에 대해 그 언어의 문법에 대한 표현을 정의하면서, 그 표현을 사용하여 해당 언어로 기술된 문장을 해석하는 해석자를 함께 정의한다.
- 단점
- 객체를 많이 만들어야 하고, 포인터에 많은 메모리를 소모한다.
- 또한 하위 표현식에 접근해야 하므로 데이터 캐시에 치명적이다.
- 이렇게 느리고 메모리가 많이 필요하기 때문에 대부분의 프로그래밍 언어는 이 패턴을 쓰진 않는다.
수식 표현식 예시 #
$$ (1 + 2) * (3 - 4)$$
- 인터프리터 패턴은 위와 같은 표현식을 추상 구문 트리로 만들고 실행 시에는 자기 자신을 해석(평가) 하게 한다.
class Expression
{
public:
virtual ~Expression() {}
// 표현식은 자기 자신을 평가한다.
virtual double evaluate() = 0;
};
class NumberExpression : public Expression
{
private:
double value;
public:
NumberExpression(double v) : value(v) {}
// 숫자는 자기 값을 그대로 평가한다.
virtual double evaluate()
{
return value;
}
};
class AdditionExpression : public Expression
{
private:
Expression* left;
Expression* right;
public:
AdditionExpression(Expression* l, Expression* r) : left(l), right(r) {}
// 더하기는 하위표현식을 재귀적으로 평가해서 더한다.
virtual double evaluate()
{
double l = left->evaluate();
double r = right->evaluate();
return l + r;
}
};
void use()
{
NumberExpression a(1);
NumberExpression b(2);
AdditionExpression add(&a, &b);
add.evalute();
}
개념적인 예시 #
// 표현식
public interface IExpression
{
bool Interpret(string context);
}
public class TerminalExpression : IExpression
{
private string data;
public TerminalExpression(string data)
{
this.data = data;
}
// 해당 표현을 해석한다
public override bool Interpret(string context)
{
if (context.contains(data))
{
return true;
}
return false;
}
}
public class AndExpression : IExpression
{
private IExpression expr1 = null;
private IExpression expr2 = null;
public AndExpression(IExpression expr1, IExpression expr2)
{
this.expr1 = expr1;
this.expr2 = expr2;
}
public override bool Interpret(string context)
{
return expr1.Interpret(context) && expr2.Interpret(context);
}
}
public class OrExpression : IExpression
{
private IExpression expr1 = null;
private IExpression expr2 = null;
public OrExpression(IExpression expr1, IExpression expr2)
{
this.expr1 = expr1;
this.expr2 = expr2;
}
public override bool Interpret(string context)
{
return expr1.Interpret(context) || expr2.Interpret(context);
}
}
class Program
{
static void Main(string[] args)
{
// 표현들
IExpression robert = new TerminalExpression("Robert");
IExpression john = new TerminalExpression("John");
IExpression julie = new TerminalExpression("Julie");
IExpression Married = new TerminalExpression("Married");
IExpression isMale = new OrExpression(robert, john);
IExpression isMarriedWoman = new AndExpression(julie, married);
// 컨텍스트
string context1 = "John";
string context2 = "Married Julie";
// 컨텍스트를 표현에 따라 해석한다.
Console.WriteLine("John is male? " + isMale.Interpret(context1)); // true
Console.WriteLine("Julie is a married women? " + isMarriedWoman.Interpret(context2)); // true
}
}