어떤 언어에 대해, 그 언어의 문법에 대한 표현을 정의하면서 그것(표현)을 사용하여 해당 언어로 기술된 문장을 해석하는 해석자를 함께 정의합니다.
특정한 종류의 문제가 자주 발생할 때는, 어떤 간결한 언어를 써서 그 문제를 문장으로 표현하는 것이 나을 수 있습니다. 그러고 나서 그 문장을 해석하는 해석자를 만들어 문장을 해석하게 하여 문제를 해결하는 것입니다. 이때, 해결에 필요한 코드를 작성하기보다는 간단한 언어로 문장을 반복적으로 작성하기만 하면 문제가 해결 될 수 있습니다.
RegularExpression 이라는 추상 클래스를 정의하고 나머지들은 이 추상 클래스를 상속하는 서브클래스로 정의
합니다. AlternationExpression, SequenceExpression, RepetitionExpression 들입니다.
이 세클래스들에 해 해당하는 문법의 규칙을 살펴보면, expression을 다시 왼편에 정의하므로 이 클래스는 자신
이 포함한 내부 표현식을 저장할 인스턴스 변수를 정의해야합니다.
문법이 정의한 각각의 정규 표현식을 추상 구문 트리로 표현할 수 있는데, 이 트리는 클래스들의 실제 인스턴스로
노드를 구성합니다. 예를 들어, 하나의 추상 구문 트리를 봅시다.
raining & (dog | cats) *
이제 정규표현식을 정의 하였으므로, RegularExpression의 서브클래스에 해석과 관련된 연산 Interpret() 연산
을 정의하여 정규 표현식을 해석하는 해석자를 만듭니다.
LiteralExpression: 자신이 정의한 문자와 일치하는 정보가 입력 매개변수에 있는지 확인합니다.
AlternationExpression: 입력 매개변수에 다른 대안 문자들과 일치하는 것이 있는지 알아봅시다
RepetitionExpression: 입력에 자신이 반복하는 표현에 대한 여러 개의 복사본이 존재하는지 확인합니다.
해석이 필요한 언어가 존재하거나 추상 구문 트리로서 그 언어의 문장을 표현하고자 한다면 해석자 패턴을 사용할
때입니다. 해석자 패턴이 가장 잘 먹힐 때를 정리하면 다음과 같습니다.
package study.designpattern;
class Context {
public boolean lookup(String str) {
return true;
}
public void assign(VariableExp exp, boolean b) {
}
}
class BooleanExp {
public BooleanExp() {
}
public boolean evaluate(Context context) {
return true;
}
public BooleanExp replace(String str, BooleanExp exp) {
return null;
}
public BooleanExp copy() {
return null;
}
}
class VariableExp extends BooleanExp{
public VariableExp(String x) {
}
@Override
public boolean evaluate(Context context) {
return super.evaluate(context);
}
@Override
public BooleanExp replace(String str, BooleanExp exp) {
return super.replace(str, exp);
}
@Override
public BooleanExp copy() {
return super.copy();
}
}
class AndExp extends BooleanExp {
public AndExp(Constant constant, VariableExp x) {
}
public AndExp(VariableExp y, NotExp notExp) {
}
@Override
public boolean evaluate(Context context) {
return super.evaluate(context);
}
@Override
public BooleanExp replace(String str, BooleanExp exp) {
return super.replace(str, exp);
}
@Override
public BooleanExp copy() {
return super.copy();
}
}
class OrExp extends BooleanExp {
public OrExp(AndExp andExp, AndExp andExp1) {
}
}
class Constant {
public Constant(boolean b) {
}
}
class NotExp {
public NotExp(VariableExp x) {
}
}
public class InterpretPattern {
public static void main(String[] args) {
// (true and x) or (y and (not x))
Context context = new Context();
VariableExp x = new VariableExp("X");
VariableExp y = new VariableExp("Y");
BooleanExp expression = new OrExp(
new AndExp(new Constant(true), x)
, new AndExp(y, new NotExp(x)));
context.assign(x, false);
context.assign(y, false);
boolean result = expression.evaluate(context);
System.out.println("result = " + result);
}
}
추상 구문 트리는 복합체 패턴의 한 인스턴스로 볼 수 있습니다. 하나의 구문 트리내에 터미널 기호를 여러 개 공유하기 위해서는 플라이트급 패턴을 적용할 수 있습니다. 해석자는 반복자 패턴을 이용해서 자신의 구조를 순회합니다. 방문자 패턴을 이용하면 하나의 클래스에 정의된 구문 트리 각 노드에 대한 상태를 관리할 수 있습니다.