Статьи

Поведенческие образцы дизайна: интерпретатор

Ранее мы рассмотрели цепочку ответственности и схему командования . Они решают разные проблемы, однако они оба делегируют действие другому компоненту, шаблоны команд всегда делегируют действие, цепочку ответственности, если действие не может быть обработано, оно будет перенаправлять его преемнику.

Мы собираемся переключить контекст и проверить шаблон интерпретатора. Шаблон интерпретатора определяет, как оценивать пользовательские языки. Примеры безграничны, например, язык spel для весны или даже язык, похожий на SQL.

Мы сделаем все просто и создадим интерпретатор для простого языка запросов только с операторами select и where. Это не невозможно в реальном мире, просто динамодинам и тому, насколько просты его выражения, примеров бесчисленное множество.

Итак, начнем с нашего интерфейса предложения.

1
2
3
4
5
package com.gkatzioura.design.behavioural.interpreter;
 
public interface Clause{
 
}

Я буду реализовывать WhereClause

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package com.gkatzioura.design.behavioural.interpreter;
 
 
public class WhereClause implements Clause {
 
    /**
     * Add values related to the where clause functions and expressions
     */
 
    public WhereClause() {
    }
 
    /**
     * Add functions for expressions for equals not equals etc.
     */
 
}

И SelectClause

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.gkatzioura.design.behavioural.interpreter;
 
import java.util.Optional;
 
public class SelectClause implements Clause {
 
    private Optional<WhereClause> optWhereClause = Optional.empty();
 
    public <T> T load(Class<T> valueType) {
 
        /**
         * Apply filter according to the where clause
         */
        if(optWhereClause.isPresent()) {
 
        }
 
        /**
         * Load data
         */
 
        /**
         * Serialize/Deserialize data based on the type
         * For example if you use jackson it will be:  new ObjectMapper().readValue("text",valueType);
         */
 
 
        return null;
    }
 
    public void setWhereClause(WhereClause whereClause) {
        this.optWhereClause = Optional.of(whereClause);
    }
}

Функция загрузки должна загружать наши данные на основе заданного выражения.

Оба предложения связаны друг с другом, однако предложение select может давать результаты, даже если операторы «где» не были даны вообще. В любом случае, когда дело доходит до загрузки данных, предложение select проверит и применит любые операторы фильтра, которые может иметь предложение where (если существует), а затем вернет данные.
Давайте перейдем к интерпретатору конкретных частей

Мы создадим интерфейс выражения.

1
2
3
4
5
6
7
package com.gkatzioura.design.behavioural.interpreter;
 
public interface Expression {
 
    Clause interpret(String context);
 
}

Толкование данного текста вернет нам пункт.

Мы создадим WhereExpression.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.gkatzioura.design.behavioural.interpreter;
 
public class WhereExpression implements Expression {
 
    @Override
    public WhereClause interpret(String context) {
        WhereClause whereClause = new WhereClause();
        /**
         * Parse the string and find any where statements ie. A=1 AND B!=2 and apply them.
         */
 
        return whereClause;
    }
 
}

И выберите выражение.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package com.gkatzioura.design.behavioural.interpreter;
 
public class SelectExpression implements Expression {
 
    @Override
    public SelectClause interpret(String context) {
        SelectClause selectClause = new SelectClause();
 
        /**
         * Parse text and check for expressions like `SELECT * FROM ` or `SELECT A,B,C FROM` .
         */
 
        return selectClause;
    }
 
}

Последним шагом будет выражение запроса.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.gkatzioura.design.behavioural.interpreter;
 
public class QueryExpression implements Expression {
 
    @Override
    public SelectClause interpret(String context) {
 
        SelectClause selectClause = new SelectExpression().interpret(context);
 
        if(context.contains("WHERE")) {
 
            WhereClause whereClause = new WhereExpression().interpret(context);
            selectClause.setWhereClause(whereClause);
        }
 
        return selectClause;
    }
 
}

Итак, давайте соединим их все вместе. Мы интерпретируем запрос, который выбирает список целых чисел.

01
02
03
04
05
06
07
08
09
10
11
12
package com.gkatzioura.design.behavioural.interpreter;
 
public class Interpreter {
 
    public static void main(String[] args) {
        String selectionString = "SELECT b FROM foo WHERE a=1";
        Integer[] values = new QueryExpression()
                .interpret(selectionString)
                .load(Integer[].class);
    }
 
}

Вы можете найти исходный код на github.

Опубликовано на Java Code Geeks с разрешения Эммануила Гкациоураса, партнера нашей программы JCG. См. Оригинальную статью здесь: Поведенческие образцы дизайна: Интерпретатор

Мнения, высказанные участниками Java Code Geeks, являются их собственными.