반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- DIP
- assertThrows
- @Configuration
- thymeleaf
- 싱글톤
- SQL
- 스프링 빈
- 스프링 부트 입문
- 스프링
- 스프링 컨테이너
- spring
- 스프링 부트 기본
- 스프링부트
- resultMap
- 스프링 부트
- 필드 주입
- kafka
- 스프링 프레임워크
- mybatis
- sqld
- Effective Java
- db
- Javascript
- 생성자 주입
- JPA
- DI
- jdbc
- java
- springboot
- assertThat
Archives
- Today
- Total
선 조치 후 분석
[Design Pattern] 행동패턴 - Interpreter 본문
728x90
반응형
SMALL
인터프리터 (Interpreter) 패턴
- 자주 등장하는 문제를 간단한 언어로 정의하고 재사용하는 패턴
- 인터프리터의 목적은 자주 사용되는 특정한 문법적 규칙이 존재한다면, 이를 일련의 규칙을 통해 언어/문법으로
- 규격화하여 해석하는 목적을 가지는 패턴 (e.g : 정규표현식)
구조
- Context : Expression에서 사용하는 모든 데이터들이 저장되어 있는 공간
- Expression : 일련의 규칙을 계산하여 결과값을 반환
- TerminalExpression : Expression을 포함하지 않고, 계산된 결과를 반환
- (종료를 포함 - 더 이상 다른 문자로 치환될 수 없는 종점 문자를 의미)
- NonTerminalExpression : Expression을 참조하여, 종료를 하지 않고 다음 규칙으로 값을 넘기는 역할
- (다른 문자로 치환)

인터프리터 (Interpreter) 패턴은 NonTerminalExpression을 통해 해석한 문자를 다음 해석이 가능한 또 다른 Expression으로 넘긴다. 그리고 TerminalExpression만 남으면, 해석된 마지막 문자를 반환하여 Interpreter로써의
기능을 수행하는 구조를 가진다. 즉, 트리(Tree) 구조를 가진다.
인터프리터 (Interpreter) 패턴 사용 전
- 후위표기법을 코드로 표현할 것이다
- 후위표기법은, 중위 연산자 (2 - 3 = -1)와 달리 연산자가 나오면 앞의 두 숫자를 연산하는 형식 (2 3 - = -2)
- '123+-'이란 형식에 대한 연산을 자주 반복해서 사용하는 경우라면 'xyz+-'라는 하나의 형식으로
- 지정하여 문법으로 지정할 수 있다.
public class PostfixNotation {
private final String expression;
public PostfixNotation(String expression) {
this.expression = expression;
}
public 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());
}
}
@Test
void test1() {
PostfixNotation postfixNotation = new PostfixNotation("123+-");
postfixNotation.calculate();
}
이를 인터프리터(Interpreter) 패턴을 사용하여 적용해 보자.
인터프리터 (Interpreter) 패턴 사용 후
- x면 x, y면 y, z면 z를 반환하면 되는 TerminalExpression이 되어 종료를 포함
- '+-'과 같은 Expression은 다른 Expression을 Interpreter 한 다음 그 결과를 연산하는 NonTerminalExpression
- 인터프리터 기능을 추상화한 Expression 클래스
- 이 인터페이스의 구현체를 TerminalExpression과 NonTerminalExpression의 성질을 담은 구현체로 기능을 캡슐화
@AllArgsConstructor
public class PlusExpression implements PostfixExpression {
private PostfixExpression left;
private PostfixExpression right;
@Override
public int intepret(Map<Character, Integer> context) {
return left.intepret(context) + right.intepret(context);
}
}
- TerminalExpression 구조를 가지는 VariableExpression 클래스
- TerminalExpression 이기 때문에, 또 다른 Expression을 반환하지 않고 종점(문자)을 반환
public class VariableExpression implements PostfixExpression {
private Character variable;
public VariableExpression(Character variable) {
this.variable = variable;
}
@Override
public int intepret(Map<java.lang.Character, Integer> context) {
return context.get(variable);
}
}
- NonTerminalExpression 구조를 가지는 연산자 클래스
- NonTerminalExpression이기 때문에 다음 표현식인 Expressoin을 반환
@AllArgsConstructor
public class PlusExpression implements PostfixExpression {
private PostfixExpression left;
private PostfixExpression right;
@Override
public int intepret(Map<Character, Integer> context) {
return left.intepret(context) + right.intepret(context);
}
}
@AllArgsConstructor
public class MinusExpression implements PostfixExpression {
private PostfixExpression left;
private PostfixExpression right;
@Override
public int intepret(Map<Character, Integer> context) {
return left.intepret(context) - right.intepret(context);
}
}
- Client : Expresson을 통해 값을 주입하여 결과를 얻는다.
- Parse : Expresson을 반환하는 별도의 Parser 클래스가 존재하는 이유는 클라이언트가 입력한 특정 규칠을
지정된 기능 (후위연산)을 수행하는 문법으로 변환하기 위함
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);
}
}
}
인터프리터 (Interpreter) 패턴
장점
- 각 문법 규칙을 클래스로 표현하기 때문에 언어를 쉽게 구현
- 문법이 클래스에 의해 표현되기에 언어를 쉽게 변경하거나 확장 가능
- 클래스 구조에 메소드만 추가하면 프로그램을 해석하는 기본 기능 외에 보기 쉽게 출력하는 기능이나
더 나은 프로그램 확인 기능 같은 새로운 기능을 추가할 수 있다.
단점
- 문법 규칙의 개수가 많아지면 복잡해진다.
- 다양한 문법이 생성될 때 성능 저하가 발생한다.
728x90
반응형
LIST
'Language > Design Pattern' 카테고리의 다른 글
[Design Pattern] 행동패턴 - Mediator (0) | 2023.11.07 |
---|---|
[Design Pattern] 행동패턴 - Iterator (0) | 2023.11.06 |
[Design Pattern] 행동패턴 - Command (0) | 2023.11.01 |
[Design Pattern] 구조패턴 - Flyweight (0) | 2023.10.30 |
[Design Pattern] 구조패턴 - Facade (0) | 2023.10.30 |