본문 바로가기
DesignPattern

[Design Pattern] Interpreter Pattern

by 봄석 2019. 10. 21.

[Design Pattern] Interpreter Pattern

 

Interpreter Pattern에 대하여 알아보고 , 자바 코틀린 예제를 봐보도록 하겠습니다.

 

 

Interpreter Pattern이란????

  • 문법 규칙을 클래스화 한 구조로써, 일련의 규칙으로 정의된 언어를 해석하는 패턴입니다.
  • 문법 규칙이 많아지면 복잡해지고 무거워지기 때문에 그럴 땐 차라리 파서/컴파일러 생성기를 쓰는 게 좋습니다.
  • 언어 분석기라고 생각하면 되며, 스크립트나 컴파일러 문법 등이 있을 수 있습니다.
  • 예로 SQL 구문이나 shell 커멘드 해석기, 통신 프로토콜 등이 있습니다.

 

 

 

특징

 

 표현(Expression) interface(혹은 abstract class)를  생성하고 Expression인터페이스를 구현하는 구상 클래스를 생성합니다.

 

 

Interpreter pattern with Java

public interface Expression {
    public boolean interpret(String context);
}
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);
   }
}
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);
   }
}
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;
   }
}
public class InterpreterPatternDemo {

   //Rule: Robert or 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 male"));
      System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));
   }
}

interpreterPatternDemo에서 규칙을  생성하고

main 함수 안에 정의된 언어   John  male  , Married Julie를 해석합니다.

 

 

 

Interpreter Pattern with Kotlin

sealed class Expression
class Constant(val value: Int) : Expression()
class Add(val left: Expression, val right: Expression) : Expression()
class Mul(val left: Expression, val right: Expression) : Expression()
class Interpreter {
    /**
     * Interprets [extension] and returns [expression] value
     */
    fun interpret(expression: Expression): Int = when (expression) {
        // recursively interpret the left and the right expressions of the nonterminal expression
        // and then apply the multiplication operation
        is Mul -> interpret(expression.left) * interpret(expression.right)
        // recursively interpret the left and the right expressions of the nonterminal expression
        // and then apply the addition operation
        is Add -> interpret(expression.left) + interpret(expression.right)
        // directly interpret the value of the terminal expression
        is Constant -> expression.value
    }
}
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class InterpreterTest {

    val interpreter = Interpreter()

    @ParameterizedTest(name = "{0} = {2}")
    @MethodSource("expressionProvider")
    fun givenExpressionAndInterpreter_whenInterpretExpression_thenReturnExpressionVaue(
        @Suppress("UNUSED_PARAMETER") expressionText: String,
        expression: Expression,
        expectedValue: Int
    ) {
        // Given & When
        val value = interpreter.interpret(expression)

        // Then
        assertThat(value,CoreMatchers.equalTo(expectedValue))
    }


    fun expressionProvider(): Stream<Arguments> = Stream.of(
            Arguments.of("1", Expression.Constant(1), 1),
            Arguments.of("1+2", Expression.Add(Expression.Constant(1), Expression.Constant(2)), 3),
            Arguments.of("1+2*3", Expression.Add(Expression.Constant(1),
                Expression.Mul(Expression.Constant(2), Expression.Constant(3))
            ), 7)
    )
}

 

 

 

정리

문법 규칙을 클래스화 한 구조로써, 일련의 규칙으로 정의된 언어를 해석하는 패턴입니다.

 

 

샘플 보러 가기

https://github.com/qjatjr1108/DesignPattern

 

qjatjr1108/DesignPattern

DesignPattern Sample. Contribute to qjatjr1108/DesignPattern development by creating an account on GitHub.

github.com

 

댓글