행위 패턴(Behavioral Pattern)
인터프리터 패턴(Interpreter Pattern)은 객체지향 디자인 패턴 중 하나로, 언어나 문법을 해석하고 실행하는 역할을 담당하는 패턴입니다.
인터프리터 패턴은 문법 규칙을 나타내는 클래스를 정의하고, 이를 해석하여 실행할 수 있는 클래스를 만들어 구성합니다. 이때 해석하는 작업은 주로 문장의 구조를 분석하고 각 구성 요소를 적절한 동작으로 변환하는 것입니다.
예를 들어, 자연어로 작성된 수학 수식을 계산하는 프로그램을 만들기 위해서는 문법 규칙을 정의하고, 이를 해석하여 수식을 계산하는 클래스를 구현해야 합니다. 이때 문법 규칙은 수식에 대한 문법적인 구조를 나타내는 클래스를 만들어 정의하고, 해석 작업은 각 구성 요소를 분석하여 적절한 계산 작업을 수행하는 클래스를 만들어 구성합니다.
인터프리터 패턴은 문법 규칙을 수정하거나 추가할 때도 유용합니다. 새로운 규칙을 추가하거나 기존 규칙을 수정하여 새로운 동작을 추가할 수 있습니다. 이때 각 규칙은 독립적으로 작동하며, 다른 규칙에 영향을 주지 않습니다.
인터프리터 패턴은 컴파일러나 인터프리터를 구현하는 데에도 활용됩니다. 컴파일러나 인터프리터는 프로그래밍 언어의 문법 규칙을 해석하여 실행 코드를 생성하거나 실행하는 역할을 수행하는데, 인터프리터 패턴을 활용하여 이를 구현할 수 있습니다.
단점으로는 복잡한 문법 규칙을 처리할 때 클래스가 많아질 수 있고, 코드의 유지보수가 어려워질 수 있다는 것이 있습니다. 따라서 인터프리터 패턴은 간단한 문법 규칙을 처리하는 경우에 적합합니다.
Interpreter 패턴 예제
인터프리터 패턴을 이용하여 간단한 계산기를 구현해보겠습니다. 계산기는 더하기와 빼기 두 가지 연산만을 지원합니다.
Diagrams
Abstract Expression 클래스
interface Expression {
int interpret();
}
Terminal Expression 클래스
class Number implements Expression {
private int number;
public Number(int number) {
this.number = number;
}
public int interpret() {
return number;
}
}
Nonterminal Expression 클래스
class Add implements Expression {
private Expression leftOperand;
private Expression rightOperand;
public Add(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret() {
return leftOperand.interpret() + rightOperand.interpret();
}
}
Nonterminal Expression 클래스
class Subtract implements Expression {
private Expression leftOperand;
private Expression rightOperand;
public Subtract(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret() {
return leftOperand.interpret() - rightOperand.interpret();
}
}
Context 클래스
class CalculatorContext {
private String expression;
public CalculatorContext(String expression) {
this.expression = expression;
}
public String getExpression() {
return expression;
}
}
Client 클래스
public class Main {
public static void main(String[] args) {
// Context 객체 생성
CalculatorContext context = new CalculatorContext("5 + 3 - 2");
// 문법 해석
Expression expression = parse(context);
// 결과 출력
System.out.println(context.getExpression() + " = " + expression.interpret());
}
private static Expression parse(CalculatorContext context) {
String[] tokens = context.getExpression().split(" ");
Stack<Expression> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
if (tokens[i].equals("+")) {
Expression left = stack.pop();
Expression right = new Number(Integer.parseInt(tokens[++i]));
stack.push(new Add(left, right));
} else if (tokens[i].equals("-")) {
Expression left = stack.pop();
Expression right = new Number(Integer.parseInt(tokens[++i]));
stack.push(new Subtract(left, right));
} else {
stack.push(new Number(Integer.parseInt(tokens[i])));
}
}
return stack.pop();
}
}
이 예제에서는 간단한 계산기를 구현하였습니다. Number 클래스는 숫자를 나타내는 클래스이고, Add 클래스와 Subtract 클래스는 더하기와 빼기를 수행하는 클래스입니다. CalculatorContext 클래스는 입력받은 표현식을 저장하고 관리하는 클래스입니다.
Client 클래스에서는 CalculatorContext 객체를 생성하고 표현식을 할당한 후, parse 메소드를 이용하여 표현식을 해석합니다. parse 메소드에서는 입력받은 표현식을 토큰으로 분리한 후, 토큰의 종류에 따라 Expression 객체를 생성하고 스택에 저장합니다. 마지막으로 Expression 인터페이스의 interpret 메소드를 호출하여 결과를 출력합니다.
예를 들어, 위 예제에서는 "5 + 3 - 2"라는 표현식을 입력받아서 "6"이라는 결과를 출력합니다.
이 예제를 보면, 인터프리터 패턴은 문법적인 규칙을 클래스로 나타내어 표현식을 해석하는 방식으로 동작합니다. 이를 통해 복잡한 문법을 간단한 클래스 구조로 표현할 수 있고, 이를 이용하여 표현식을 해석할 수 있습니다.
또한, 인터프리터 패턴은 문법적인 규칙이 변경되더라도 기존의 클래스 구조를 변경하지 않아도 되므로, 유연성과 확장성이 높은 패턴입니다.
이와 같이 인터프리터 패턴은 복잡한 문법을 클래스 구조로 나타내어 표현식을 해석하는 방식으로 동작합니다. 이를 이용하면, 다양한 영역에서 문법적인 규칙을 클래스로 표현할 수 있으며, 이를 통해 문제를 해결할 수 있습니다.
'JAVA > 디자인 패턴' 카테고리의 다른 글
[Design Pattern] Mediator(중재자) 패턴이란? (0) | 2023.05.08 |
---|---|
[Design Pattern] Iterator(반복자) 패턴이란? (0) | 2023.05.08 |
[Design Pattern] Command(커맨드) 패턴이란? (0) | 2023.05.07 |
[Design Pattern] Chain of Responsibility(책임 연쇄) 패턴이란? (0) | 2023.05.07 |
[Design Pattern] Prototype(프로토타입) 패턴이란? (0) | 2023.05.06 |