Interpreter

GamSa Ham·2022년 11월 4일
0

GoF디자인패턴

목록 보기
11/22

의도

어떤 언어에 대해, 그 언어의 문법에 대한 표현을 정의하면서 그것(표현)을 사용하여 해당 언어로 기술된 문장을 해석하는 해석자를 함께 정의합니다.

동기

특정한 종류의 문제가 자주 발생할 때는, 어떤 간결한 언어를 써서 그 문제를 문장으로 표현하는 것이 나을 수 있습니다. 그러고 나서 그 문장을 해석하는 해석자를 만들어 문장을 해석하게 하여 문제를 해결하는 것입니다. 이때, 해결에 필요한 코드를 작성하기보다는 간단한 언어로 문장을 반복적으로 작성하기만 하면 문제가 해결 될 수 있습니다.

RegularExpression 이라는 추상 클래스를 정의하고 나머지들은 이 추상 클래스를 상속하는 서브클래스로 정의

합니다. AlternationExpression, SequenceExpression, RepetitionExpression 들입니다.

이 세클래스들에 해 해당하는 문법의 규칙을 살펴보면, expression을 다시 왼편에 정의하므로 이 클래스는 자신

이 포함한 내부 표현식을 저장할 인스턴스 변수를 정의해야합니다.

문법이 정의한 각각의 정규 표현식을 추상 구문 트리로 표현할 수 있는데, 이 트리는 클래스들의 실제 인스턴스로

노드를 구성합니다. 예를 들어, 하나의 추상 구문 트리를 봅시다.

raining & (dog | cats) *

이제 정규표현식을 정의 하였으므로, RegularExpression의 서브클래스에 해석과 관련된 연산 Interpret() 연산

을 정의하여 정규 표현식을 해석하는 해석자를 만듭니다.

LiteralExpression: 자신이 정의한 문자와 일치하는 정보가 입력 매개변수에 있는지 확인합니다.

AlternationExpression: 입력 매개변수에 다른 대안 문자들과 일치하는 것이 있는지 알아봅시다

RepetitionExpression: 입력에 자신이 반복하는 표현에 대한 여러 개의 복사본이 존재하는지 확인합니다.

활용성

해석이 필요한 언어가 존재하거나 추상 구문 트리로서 그 언어의 문장을 표현하고자 한다면 해석자 패턴을 사용할

때입니다. 해석자 패턴이 가장 잘 먹힐 때를 정리하면 다음과 같습니다.

  • 정의할 언어의 문법이 간단합니다. 문법이 복잡하다면 문법을 정의하는 클래스 계통이 복잡해지고 관리 할 수 없게 됩니다.
  • 효율성은 별로 고려할 사항이 아닙니다. 정규표현식은 일반적으로 유한 상태기계 개념으로 변역합니다. 이때에도 정규 표현식을 유한 상태 기계로 변형하는 번역기를 구현해야 하는데, 역시 해석자 패턴을 적용할 수 있습니다.

구조

참여자

  • AbstactExpression(RegularExpression): 추상 구문 트리에 속한 모든 노드에 해당하는 클래스들이 공통적으로 가져야할 Interpret() 연산을 추상 연산으로 정의합니다.
  • TerminalExpression(LiteralExpression): 문법에 정의한 터미널 기호와 관련된 해석 방법을 구현합니다.
  • NonterminalExpression(AlternationExpression, RepetitionExpression, SequenceExpressions)문법의 오른편에 나타나는 모든 기호에 대해서 클래스를 정의해야합니다.
  • Context: 번역기에 대한 포괄적인 정보를 포함합니다
  • Client: 언어로 정의한 특정 문장을 나타내는 추상 구문 트리입니다. 이 추상 구문 트리는 NonterminalExpresion과 TerminalExpresion 클래스의 인스턴스로 구성됩니다. 이 인스턴스는 interpret() 연산을 호합니다.

예제 코드

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);
    }

}

관련패턴

추상 구문 트리는 복합체 패턴의 한 인스턴스로 볼 수 있습니다. 하나의 구문 트리내에 터미널 기호를 여러 개 공유하기 위해서는 플라이트급 패턴을 적용할 수 있습니다. 해석자는 반복자 패턴을 이용해서 자신의 구조를 순회합니다. 방문자 패턴을 이용하면 하나의 클래스에 정의된 구문 트리 각 노드에 대한 상태를 관리할 수 있습니다.

profile
안녕하세요. 자바를 좋아하고 디자인 패턴, Refactoring, Clean Code에 관심이 많은 백엔드 개발자입니다.

0개의 댓글