인터프리터 패턴은 주어진 언어의 문법을 나타내는 클래스를 이용해 문장을 해석하고 실해앟는 디자인 패턴이다. 주로 특정 도메인 언어 (DSL, Domain-Specific Language)의 구문 해석에 사용된다. 인터프리터 패턴은 언어의 각 기호를 클래스 하나로 표현하고, 이를 조합하여 문장을 해석하는 구조를 제공한다.
주요 개념 부터 알아보자
1. AbstractExpression (추상 표현) : 모든 표현식의 공통 인터페이스를 정의한다.
2. TerminalExpression (종료 표현) : 문법의 기본 요소를 정의하며, 해석의 최종 단계를 나타낸다.
3. NonTerminalExpression (비종료 표현) : 문법의 조합 규칙을 정의하며, 다른 표현식을 결합한다.
4. Context (문맥) : 해석에 필요한 정보를 저장한다.
5. Client (클라이언트) : 문장을 구성하고 해석을 시작한다.
예시소스코드를 살펴보자.
수학 표현식을 해석하고 계산하는 인터프리터 패턴을 구현한다.
1. AbstractExpression 인터페이스
// AbstractExpression 인터페이스: 표현식의 공통 인터페이스 정의
interface Expression {
int interpret();
}
2. TerminalExpression 클래스
// Number 클래스: 숫자 표현식 (종료 표현)
class Number implements Expression {
private int number;
public Number(int number) {
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
3. NonTerminalExpression 클래스
// Addition 클래스: 덧셈 표현식 (비종료 표현)
class Addition implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public Addition(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public int interpret() {
return leftExpression.interpret() + rightExpression.interpret();
}
}
// Subtraction 클래스: 뺄셈 표현식 (비종료 표현)
class Subtraction implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public Subtraction(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public int interpret() {
return leftExpression.interpret() - rightExpression.interpret();
}
}
4. Client 클래스
// Client 클래스: 수학 표현식을 구성하고 해석을 시작
public class InterpreterPatternDemo {
public static void main(String[] args) {
// 표현식: (5 + 3) - (2 + 1)
Expression expr1 = new Addition(new Number(5), new Number(3));
Expression expr2 = new Addition(new Number(2), new Number(1));
Expression mainExpr = new Subtraction(expr1, expr2);
// 해석 및 결과 출력
int result = mainExpr.interpret();
System.out.println("Result: " + result); // 출력: Result: 5
}
}
AbstractExpression 인터페이스: interpret 메서드를 정의하여 모든 표현식의 공통 인터페이스를 제공한다.
TerminalExpression 클래스: 기본적인 숫자와 같은 종료 표현식을 정의한다.
NonTerminalExpression 클래스: 덧셈, 뺄셈 등의 비종료 표현식을 정의하며, 다른 표현식을 결합하여 더 복잡한 표현식을 만든다.
Client 클래스: 표현식을 구성하고 해석을 시작한다.
현업에서 주로 사용하는 부분은 이커머스의 할인쪽 로직을 구현하기도 하다.
// Expression 인터페이스: 모든 표현식의 공통 인터페이스 정의
interface Expression {
boolean interpret(Order order);
}
// TerminalExpression 클래스: 간단한 조건 표현식 정의
class MinimumAmountExpression implements Expression {
private double amount;
public MinimumAmountExpression(double amount) {
this.amount = amount;
}
@Override
public boolean interpret(Order order) {
return order.getTotalAmount() >= amount;
}
}
class CustomerTypeExpression implements Expression {
private String customerType;
public CustomerTypeExpression(String customerType) {
this.customerType = customerType;
}
@Override
public boolean interpret(Order order) {
return order.getCustomerType().equalsIgnoreCase(customerType);
}
}
// AndExpression 클래스: 두 표현식을 AND 연산으로 결합
class AndExpression implements Expression {
private Expression expr1;
private Expression expr2;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(Order order) {
return expr1.interpret(order) && expr2.interpret(order);
}
}
// Order 클래스: 해석 대상이 되는 주문 정보
class Order {
private double totalAmount;
private String customerType;
public Order(double totalAmount, String customerType) {
this.totalAmount = totalAmount;
this.customerType = customerType;
}
public double getTotalAmount() {
return totalAmount;
}
public String getCustomerType() {
return customerType;
}
}
// Client 클래스: 비즈니스 규칙을 구성하고 해석
public class InterpreterPatternBusinessRuleDemo {
public static void main(String[] args) {
// 주문 생성
Order order = new Order(150.0, "Regular");
// 할인 규칙 정의
Expression rule = new AndExpression(
new MinimumAmountExpression(100.0),
new CustomerTypeExpression("Regular")
);
// 규칙 해석 및 적용
boolean isEligibleForDiscount = rule.interpret(order);
System.out.println("Is order eligible for discount? " + isEligibleForDiscount);
}
}
//출력
//Is order eligible for discount? true
현업에서는 사실 많이 쓰이지는 않는다. 대체적으로 복잡한 경우가 많고, 성능에서도 여러 규칙을 해석할때 문제가 될 수 있기 때문이다.
'Design Pattern > 행동 패턴(Behavioral Patterns)' 카테고리의 다른 글
메멘토(Memento) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
---|---|
중재자(Mediator) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
반복자(Iterator) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
커맨드(Command) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
책임 연쇄(Chain of Responsibility) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |