문법 규칙을 클래스화 한 구조로, 일련의 규칙으로 정의된 문법적 언어를 해석하는 패턴.
인터프리터 패턴 특징
장점
•
행위(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
복사