인터프리터(Interpreter) 패턴
디자인 패턴 ·인터프리터 패턴은 언어나 문법을 해석하고 실행하는 디자인 패턴입니다. 언어나 문법을 해석하기 위한 인터프리터를 구현하고, 이를 이용해 원하는 기능을 수행합니다. 이 패턴은 주로 컴파일러나 인터프리터를 만드는 데 사용됩니다.
구성 요소
- AbstractExpression(추상 표현식) : 모든 표현식에서 공통적으로 사용되는 인터페이스를 정의합니다.
- TerminalExpression(종료 표현식) : 표현식에서 종료역할을 수행합니다.
- NonterminalExpression(비종료 표현식) : 표현식에서 비종료역할을 수행합니다.
- Context(컨텍스트) : 인터프리터에서 전역적으로 사용되는 정보를 저장합니다.
구현:
- 추상 표현식(AbstractExpression) 클래스를 정의합니다. 이 클래스는 모든 표현식에서 공통적으로 사용되는 인터페이스를 정의합니다.
- 종료 표현식(TerminalExpression) 클래스를 만듭니다. 이 클래스는 표현식에서 종료 역할을 수행합니다.
- 비종료 표현식(NonterminalExpression) 클래스를 만듭니다. 이 클래스는 표현식에서 비종료역할을 수행합니다.
- 컨텍스트(Context) 클래스를 만듭니다. 이 클래스는 인터프리터에서 전역적으로 사용되는 정보를 저장합니다.
- 클라이언트에서 컨텍스트(Context) 객체를 생성하고, 인터프리터(Interpreter) 객체를 생성합니다.
- 클라이언트에서 인터프리터(Interpreter) 객체를 사용하여 문장을 해석합니다.
장점
- 새로운 언어나 문법을 쉽게 추가할 수 있습니다.
- 구문 분석을 위한 별도의 클래스나 라이브러리가 필요하지 않습니다.
- 코드의 유연성을 높일 수 있습니다.
단점
- 복잡한 문법이나 언어를 다루기에는 적합하지 않습니다.
- 각 표현식이 개별적으로 정의되어 있어야 하기 때문에, 클래스의 수가 증가할 수 있습니다.
- 실행 시간이 오래 걸릴 수 있습니다.
예시
더하기, 빼기 기능을 수행할 수 있는 간단한 전위 연산 계산기를 만들려고한다.
AbstractExpression
public interface PostFixExpression {
int interpret(Map<Character, Integer> context);
}
TerminalExpression
public class VariableExpression implements PostFixExpression {
private final char character;
public VariableExpression(char character) {
this.character = character;
}
@Override
public int interpret(Map<Character, Integer> context) {
return context.get(character);
}
}
NonterminalExpression
public class MinusExpression implements PostFixExpression {
private final PostFixExpression left;
private final 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 PlusExpression implements PostFixExpression {
private final PostFixExpression left;
private final 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);
}
}
Context
java.util.Map;
Client
public class PostFixParser {
public static PostFixExpression parse(String text) {
Stack<PostFixExpression> stack = new Stack<>();
for (char c : text.toCharArray()) {
switch (c) {
case '+':
stack.push(new PlusExpression(stack.pop(), stack.pop()));
break;
case '-':
PostFixExpression right = stack.pop();
PostFixExpression left = stack.pop();
stack.push(new MinusExpression(left, right));
break;
default:
stack.push(new VariableExpression(c));
}
}
return stack.pop();
}
}
class PostfixNotationTest {
@Test
public void calculate_test() {
PostFixExpression expression = PostFixParser.parse("xyz+-");
int result = expression.interpret(Map.of(
'x', 1,
'y', 2,
'z', 3
));
assertEquals(-4, result);
}
}
결론
인터프리터 패턴은 언어나 문법을 해석하고 실행하는 데 사용되는 디자인 패턴입니다. 이 패턴은 주로 컴파일러나 인터프리터를 만드는 데 사용됩니다. 인터프리터 패턴을 사용하면 새로운 언어나 문법을 쉽게 추가할 수 있으며, 코드의 유연성을 높일 수 있습니다.
예제는 이곳 에서 확인하실수 있습니다.