[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
'DesignPattern' 카테고리의 다른 글
[Design Pattern] Chain of Responsibility Pattern (0) | 2019.10.21 |
---|---|
[Design Pattern] Command Pattern (0) | 2019.10.21 |
[Design Pattern] Iterator Pattern (0) | 2019.10.18 |
[Design Pattern] Mediator Pattern (0) | 2019.10.18 |
[Design Pattern] Memento Pattern (0) | 2019.10.17 |
댓글