티스토리 뷰
728x90
1. 의미
- 인터프리터(interpreter) 사전적 의미 → 통역, 연주자
- 자주 등장하는 문제를 간단한 언어로 정의하여 재사용하는 패턴
- 반복되는 문제 패턴을 언어 또는 문법으로 정의하고 확장
- 패턴이나 언어, 문법등으로 정의하여 이슈 발생시 대입하여 사용
- 정규식을 일종의 인터프리터로 본다.
- context
- 글로벌 변수, 모든 expression에서 사용되는 정보
- expression
- interpret(context), context에 있는 값을 참조
- 1. terminal expression
- 자체 종료
- 2. non terminal expression
- 다른 expression을 참조해 봐야 결과를 확인, 다른 expression을 참조(재귀)
- terminal 을 참조할 수 있고 다른 non terminal expression을 참조
2. 적용하기
- 후위표기법(postfix)를 이용한 사칙연산 인터프리터 개발
2.1. 패턴 적용전
public class PostfixNotation {
private final String expression;
public PostfixNotation(String expression) {
this.expression = expression;
}
public static void main(String[] args) {
PostfixNotation postfixNotation = new PostfixNotation("123+-");
// 자주 사용하는 문제
// 123+- post fix를 사용하는 문자열
postfixNotation.calculate();
}
private void calculate() {
Stack<Integer> numbers = new Stack<>();
for (char c : this.expression.toCharArray()) {
switch (c) {
case '+':
numbers.push(numbers.pop() + numbers.pop());
break;
case '-':
int right = numbers.pop();
int left = numbers.pop();
numbers.push(left - right);
break;
default:
numbers.push(Integer.parseInt(c + ""));
}
}
System.out.println(numbers.pop());
}
}
2.2. 인터프리터 패턴 적용 후
public interface PostfixExpression {
int interpret(Map<Character, Integer> context);
}
public class VariableExpression implements PostfixExpression {
private Character character;
public VariableExpression(Character character) {
this.character = character;
}
@Override
public int interpret(Map<Character, Integer> context) {
return context.get(this.character);
}
}
public class PlusExpression implements PostfixExpression {
private PostfixExpression left;
private PostfixExpression right;
public PlusExpression(PostfixExpression left, PostfixExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Map<Character, Integer> context) {
return left.interpret(context) + right.interpret(context);
}
}
public class MinusExpression implements PostfixExpression {
private PostfixExpression left;
private PostfixExpression right;
public MinusExpression(PostfixExpression left, PostfixExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Map<Character, Integer> context) {
return left.interpret(context) - right.interpret(context);
}
}
public class MultiplyExpression implements PostfixExpression{
private PostfixExpression left, right;
public MultiplyExpression(PostfixExpression left, PostfixExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Map<Character, Integer> context) {
return left.interpret(context) * right.interpret(context);
}
}
public class PostfixParser {
public static PostfixExpression parse(String expression) {
Stack<PostfixExpression> stack = new Stack<>();
for (char c : expression.toCharArray()) {
stack.push(getExpression(c, stack));
}
return stack.pop();
}
private static PostfixExpression getExpression(char c, Stack<PostfixExpression> stack) {
switch (c) {
case '+':
return new PlusExpression(stack.pop(), stack.pop());
case '-':
PostfixExpression right = stack.pop();
PostfixExpression left = stack.pop();
return new MinusExpression(left, right);
default:
return new VariableExpression(c);
}
}
}
public static void main(String[] args) {
PostfixExpression expression = PostfixParser.parse("xyz+-a+");
int result = expression.interpret(Map.of('x', 1, 'y', 2, 'z', 3, 'a', 4));
System.out.println(result);
}
3. 장단점
3.1. 장점
- 자주 등장하는 문제 패턴을 언어와 문법으로 정의할 수 있다
- 기존 코드를 변경하지 않고 새로운 expression을 추가할 수 있다
- expression이 본인의 기능인 하나의 기능만한다
- SRP (Single Responsibility Principle)
3.2. 단점
- 복잡한 문법을 표현하려면 expression 과 parser가 복잡해진다
728x90
'디자인 패턴' 카테고리의 다른 글
17. 중재자 패턴 (0) | 2022.02.10 |
---|---|
16. 이터레이터 패턴 (0) | 2022.02.10 |
14. 커맨드 패턴 (0) | 2022.02.10 |
13. 책임연쇄패턴 (0) | 2022.02.10 |
12. 프록시 패턴 (0) | 2022.02.10 |
댓글