반응형
디자인패턴
[Java][디자인 패턴] 24. 인터프리터 패턴 (Interpreter Pattern)
인터프리터 패턴은 간단한 언어적 문법을 표현하는 패턴이다.
인터프리터 패턴이란?
- 프로그램을 여러 시스템 환경에서 구동하기 위해서는 추상화된 언어의 해석 과정이 필요하다.
- 이 과정에서 언어적 해석을 담당하는 것이 바로 인터프리터(해석자) 패턴이다.
인터프리터 패턴 구조
- 추상 구문 트리 인터페이스 (Abstract Expression)
- 종료 기호(Terminal Expression)
- 비종료 기호(Non-Terminal Expression)
- 해석기 정보(Context)
- 문장을 나타내는 추상 구문 트리(Client)
일반적인 상황에서 해석자패턴을 직접 구현하는 일은 거의 없을거라고 생각되고 적절한 예시 코드가 떠오르지 않아 링크 코드를 참고했다.
인터프리터 패턴 코드
1. Expression 인터페이스
interface Expression {
List<String> interpret(Context ctx);
}
2. Context 클래스
class Context {
private static Map<String, List<Row>> tables = new HashMap<>();
static {
List<Row> list = new ArrayList<>();
list.add(new Row("John", "Doe"));
list.add(new Row("Jan", "Kowalski"));
list.add(new Row("Dominic", "Doom"));
tables.put("people", list);
}
private String table;
private String column;
/**
* Index of column to be shown in result.
* Calculated in {@link #setColumnMapper()}
*/
private int colIndex = -1;
/**
* Default setup, used for clearing the context for next queries.
* See {@link Context#clear()}
*/
private static final Predicate<String> matchAnyString = s -> s.length() > 0;
private static final Function<String, Stream<? extends String>> matchAllColumns = Stream::of;
/**
* Varies based on setup in subclasses of {@link Expression}
*/
private Predicate<String> whereFilter = matchAnyString;
private Function<String, Stream<? extends String>> columnMapper = matchAllColumns;
void setColumn(String column) {
this.column = column;
setColumnMapper();
}
void setTable(String table) {
this.table = table;
}
void setFilter(Predicate<String> filter) {
whereFilter = filter;
}
/**
* Clears the context to defaults.
* No filters, match all columns.
*/
void clear() {
column = "";
columnMapper = matchAllColumns;
whereFilter = matchAnyString;
}
List<String> search() {
List<String> result = tables.entrySet()
.stream()
.filter(entry -> entry.getKey().equalsIgnoreCase(table))
.flatMap(entry -> Stream.of(entry.getValue()))
.flatMap(Collection::stream)
.map(Row::toString)
.flatMap(columnMapper)
.filter(whereFilter)
.collect(Collectors.toList());
clear();
return result;
}
/**
* Sets column mapper based on {@link #column} attribute.
* Note: If column is unknown, will remain to look for all columns.
*/
private void setColumnMapper() {
switch (column) {
case "*":
colIndex = -1;
break;
case "name":
colIndex = 0;
break;
case "surname":
colIndex = 1;
break;
}
if (colIndex != -1) {
columnMapper = s -> Stream.of(s.split(" ")[colIndex]);
}
}
}
3. From, Select, Where 클래스
class From implements Expression {
private String table;
private Where where;
From(String table) {
this.table = table;
}
From(String table, Where where) {
this.table = table;
this.where = where;
}
@Override
public List<String> interpret(Context ctx) {
ctx.setTable(table);
if (where == null) {
return ctx.search();
}
return where.interpret(ctx);
}
}
class Select implements Expression {
private String column;
private From from;
Select(String column, From from) {
this.column = column;
this.from = from;
}
@Override
public List<String> interpret(Context ctx) {
ctx.setColumn(column);
return from.interpret(ctx);
}
}
class Where implements Expression {
private Predicate<String> filter;
Where(Predicate<String> filter) {
this.filter = filter;
}
@Override
public List<String> interpret(Context ctx) {
ctx.setFilter(filter);
return ctx.search();
}
}
6. 테스트코드
class ExpressionTest {
@Test
@DisplayName("인터프리터 SQL 패턴 테스트")
void test() {
Expression query = new Select("name", new From("people"));
Context ctx = new Context();
List<String> result = query.interpret(ctx);
System.out.println(result);
Expression query2 = new Select("*", new From("people"));
List<String> result2 = query2.interpret(ctx);
System.out.println(result2);
Expression query3 = new Select("name", new From("people", new Where(name -> name.toLowerCase().startsWith("d"))));
List<String> result3 = query3.interpret(ctx);
System.out.println(result3);
}
}
원본 코드
https://www.baeldung.com/java-interpreter-pattern
참고 자료
1.쉽게 바로 써먹는 디자인 패턴 책
http://www.yes24.com/Product/Goods/93173296
반응형
'개발 > 디자인패턴' 카테고리의 다른 글
[Java][디자인 패턴] 23. 전략 패턴 (Strategy Pattern) (0) | 2022.03.27 |
---|---|
[Java][디자인 패턴] 22. 템플릿 메서드 패턴 (1) | 2022.03.26 |
[Java][디자인 패턴] 21. 메멘토 패턴 (Memento Pattern) (0) | 2022.03.25 |
[Java][디자인 패턴] 20. 상태 패턴 (State Pattern) (0) | 2022.03.25 |
[Java][디자인 패턴] 19. 중재자 패턴 (Mediator Pattern) (0) | 2022.03.24 |