Updated:

1. 개요

언어의 문법에 대한 표현과 문장의 해석자를 함께 정의하는 패턴

해석자 패턴(Interpreter Pattern)은 행동 패턴(Behavioral Pattern)의 한 종류로, 문법 규칙을 클래스화 한 구조이며, 일련의 규칙으로 정의된 문법적 언어를 해석하는 패턴이다.

2. 행동 패턴(Behavioral Pattern)

2-1. 행동 패턴이란?

행동 패턴이란 처리의 책임을 어떤 객체에게 할당하는 것이 좋은지, 알고리즘을 어떤 객체에 정의하는 것이 좋은지 등의 책임 분배와 관련된 패턴이다.

2-2. 행동 패턴 종류

3. 구성

[출처 : GoF의 디자인 패턴]

  • AbstractExpression : 모든 노드에 해당하는 클래스들이 공통으로 가져야 할 Interpret() 연산을 정의한 클래스

  • TerminalExpression : 문장의 종료를 나타내는 AbstractExpression 구현체

  • NonterminalExpression : 문장의 비종료를 나타내는 AbstractExpression 구현체

  • Context : String 표현식으로, Interpreter에 보내는 정보

  • Client : interpret() 연산을 호출하는 클래스

4. 예제 코드

Interpreter Pattern을 이용하여 남자인지, 결혼한 여자인지를 판별하는 코드를 구현해보자. (출처 : https://www.tutorialspoint.com/design_pattern/interpreter_pattern.htm)

4-1. AbstractExpression

[Expression.java]

1
2
3
4
public interface Expression {

    public boolean interpret(String context);
}

4-2. TerminalExpression

[TerminalExpression.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TerminalExpression implements Expression {

    private String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    @Override
    public boolean interpret(String context) {
        if(context.contains(data)) {
            return true;
        }
        return false;
    }
}

4-3. NonterminalExpression

[OrExpression.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class OrExpression implements Expression {

    private Expression expr1 = null;
    private Expression expr2 = null;

    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}

[OrExpression.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AndExpression implements Expression {

    private Expression expr1 = null;
    private Expression expr2 = null;

    public AndExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) && expr2.interpret(context);
    }
}

5. 테스트

[Clinet.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Client {

    //Rule: Robert and John are male
    public static Expression getMaleExpression(){
        Expression robert = new TerminalExpression("Robert");
        Expression john = new TerminalExpression("John");
        return new OrExpression(robert, john);
    }

    //Rule: Julie is a married women
    public static Expression getMarriedWomanExpression(){
        Expression julie = new TerminalExpression("Julie");
        Expression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }

    public static void main(String[] args) {
        Expression isMale = getMaleExpression();
        Expression isMarriedWoman = getMarriedWomanExpression();

        System.out.println("John is male? " + isMale.interpret("John"));
        System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));
    }
}

[실행 결과]

6. 특징

  • 확장의 용이성 : 상속을 이용하여 손쉽게 문법의 변경과 확장 가능

  • 관리의 어려움 : 규칙별로 최소 하나의 클래스가 필요하므로, 복잡한 규칙의 문법은 관리가 어려움

Updated:

Leave a comment