Interpreter Pattern

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

인터프리터 패턴 특징

장점
행위(Behavioral) 패턴
클래스 구조에 메소드만 추가하면 프로그램을 해석하는 기본 기능 외에 보기 쉽게 출력하는 기능이나 더 나은 프로그램 확인 기능 같은 새로운 기능을 추가할 수 있다.
문법의 추가 및 수정, 구현이 쉬워진다.
일종의 DSL을 만들수 있다. (Domain Specific Language) → 특정 영역을 타겟하고 있는 언어. 어떤 목적이 있고 그 목적만 달성할 수 있는 언어. ex) SQL
단점
복잡한 문법일수록 관리 및 유지가 점점 어려워진다.
다양한 문법을 생성할 수록 성능 저하를 만들수 있다.

인터프리터 패턴 의 클래스 다이어그램

예제 (왼쪽 - Java / 오른쪽 - JS)

Expression.class
public interface Expression { boolean interpreter(String con); }
Java
복사
export interface Expression { interpreter(context: string): boolean; }
JavaScript
복사
Expression interface 선언
TerminalExpression.class
public class TerminalExpression implements Expression { private String data; public TerminalExpression(String data){ this.data = data; } @Override public boolean interpreter(String context) { if(context.contains(data)){ return true; } return false; } }
Java
복사
import { Expression } from './Expression'; export class TerminalExpression implements Expression { data: string; constructor(data: string) { this.data = data; } // Override interpreter(context: string): boolean { if (context.includes(this.data)) { return true; } return false; } }
JavaScript
복사
TerminalExpression을 통해 데이터를 저장
AndExpression.class
public class AndExpression implements Expression { private Expression expr1 = null; // Julie private Expression expr2 = null; // Married public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpreter(String context) { return expr1.interpreter(context) && expr2.interpreter(context); } }
Java
복사
import { Expression } from './Expression'; export class AndExpression implements Expression { private expr1: Expression | null = null; private expr2: Expression | null = null; constructor(expr1: Expression, expr2: Expression) { this.expr1 = expr1; this.expr2 = expr2; } // Override interpreter(context: string): boolean { return this.expr1.interpreter(context) && this.expr2.interpreter(context); } }
JavaScript
복사
OrExpression.class
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 interpreter(String context) { return expr1.interpreter(context) || expr2.interpreter(context); } }
Java
복사
import { Expression } from './Expression'; export class OrExpression implements Expression { private expr1: Expression | null = null; private expr2: Expression | null = null; constructor(expr1: Expression, expr2: Expression) { this.expr1 = expr1; this.expr2 = expr2; } // Override interpreter(context: string): boolean { return this.expr1.interpreter(context) || this.expr2.interpreter(context); } }
Java
복사
interpreter 구현체
TerminalExpression 을 주입받아 생성하고 비교하는 기능을 이용.
Main.class
public class Main { public static Expression getMaleExpression(){ Expression robert = new TerminalExpression("Robert"); Expression john = new TerminalExpression("John"); return new OrExpression(robert, john); } 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.interpreter("John")); System.out.println("Julie is a married women? " + isMarriedWoman.interpreter("Married Julie")); } }
Java
복사
html + Main.js
import { AndExpression } from './ts/AndExpression'; import { OrExpression } from './ts/OrExpression'; import { TerminalExpression } from './ts/TerminalExpression'; const $andButton = <HTMLInputElement>document.getElementById('and-button'); const $andAnswer = <HTMLInputElement>document.getElementById('and-answer'); const $orButton = <HTMLInputElement>document.getElementById('or-button'); const $orAnswer = <HTMLInputElement>document.getElementById('or-answer'); $andButton.onclick = () => { const $andInput1 = (<HTMLInputElement>document.getElementById('and-input1')).value; const $andInput2 = (<HTMLInputElement>document.getElementById('and-input2')).value; const $andInput3 = (<HTMLInputElement>document.getElementById('and-input3')).value; const exp1 = new TerminalExpression($andInput1); const exp2 = new TerminalExpression($andInput2); const resultExp = new AndExpression(exp1, exp2); $andAnswer.innerHTML = `${resultExp.interpreter($andInput3)}`; }; $orButton.onclick = () => { const $orInput1 = (<HTMLInputElement>document.getElementById('or-input1')).value; const $orInput2 = (<HTMLInputElement>document.getElementById('or-input2')).value; const $orInput3 = (<HTMLInputElement>document.getElementById('or-input3')).value; const exp1 = new TerminalExpression($orInput1); const exp2 = new TerminalExpression($orInput2); const resultExp = new OrExpression(exp1, exp2); $orAnswer.innerHTML = `${resultExp.interpreter($orInput3)}`; };
JavaScript
복사
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script defer type="application/javascript" src="index.js"></script> <title>인터프리터</title> </head> <body> <div> <div> <div>글자 합치기</div> <input id="and-input1"/> <input id="and-input2"/> </div> <div>합친 내용 : </div> <input id="and-input3"/> <button id="and-button">성공여부 : </button> <div id="and-answer"></div> </div> <br/> <div> 성별맞추기 <div> 이름1 : <input id="or-input1"/> 이름2 : <input id="or-input2"/> </div> <input id="or-input3"/>은 남성인가요? <button id="or-button">결과 : </button> <div id="or-answer"></div> </div> </body> </html>
HTML
복사

실행결과

>>>John is male? true >>>Julie is a married women? true
Plain Text
복사

Reference