Книга доктора Яна Хонга «JAVA и шаблоны» начинается с описания шаблона «Интерпретатор»:
Шаблон интерпретатора — это шаблон поведения классов. Для данного языка шаблон интерпретатора определяет представление его грамматики и предоставляет интерпретатор. Клиенты могут использовать этот переводчик для перевода предложений на этом языке.
Структура режима переводчика
Давайте возьмем схематическую систему в качестве примера, чтобы обсудить структуру режима интерпретатора. Схема структуры системы выглядит следующим образом:
В шаблоне задействованы следующие роли:
(1) Роль абстрактного выражения (выражения): объявите абстрактный интерфейс, который должны реализовать все конкретные роли выражения. Этот интерфейс в основном представляет собой метод интерпретации(), называемый операцией интерпретации.
(2) Роль терминального выражения: реализует интерфейс, требуемый ролью абстрактного выражения, в основном метод интерпретировать(), каждый терминальный символ в грамматике имеет соответствующее ему конкретное терминальное выражение. Например, существует простая формула R=R1+R2, в которой R1 и R2 — терминальные символы, а соответствующий интерпретатор, анализирующий R1 и R2, — терминальное выражение.
(3) Роль нетерминального выражения: каждое правило в грамматике требует определенного нетерминального выражения. Нетерминальные выражения обычно представляют собой операторы или другие ключевые слова в грамматике, например формулы. В R=R1+R2 «+» является нетерминальным символом. , а интерпретатор, который анализирует "+", представляет собой нетерминальное символьное выражение.
(4) Роль контекста. Задача этой роли обычно состоит в сохранении конкретных значений, соответствующих каждому терминальному символу в грамматике. Например, R=R1+R2, мы присваиваем значение 100 R1 и значение R1. 200 до 2 руб. Эту информацию необходимо хранить в роли среды. Во многих случаях нам достаточно использовать Map в качестве роли среды.
Чтобы проиллюстрировать реализацию режима интерпретатора, вот простейшая грамматика и соответствующая реализация режима интерпретатора, которая предназначена для моделирования работы и оценки логических выражений на языке Java.
Терминальными символами в этом языке являются логические переменные, то есть константы true и false. Нетерминальные выражения включают логические выражения, такие как операторы и или и нет. Эта простая грамматика выглядит следующим образом:
Скопируйте код кода следующим образом:
Выражение ::= Константа | Или | Не |
И ::= Выражение Выражение «И»
Или ::= Выражение Выражение 'ИЛИ'
Not ::= Выражение 'NOT'
Переменная ::= любой идентификатор
Константа ::= 'истина' |
Структурная схема режима переводчика выглядит следующим образом:
исходный код
роль абстрактного выражения
Скопируйте код кода следующим образом:
публичный абстрактный класс Expression {
/**
* В зависимости от среды этот метод интерпретирует любое заданное выражение.
*/
публичная абстрактная логическая интерпретация (Context ctx);
/**
* Проверьте, являются ли два выражения структурно одинаковыми.
*/
общедоступное абстрактное логическое значение равно (Object obj);
/**
* Возвращает хеш-код выражения
*/
публичный абстрактный int hashCode();
/**
* Преобразуйте выражение в строку
*/
публичная абстрактная строка toString();
}
Объект Constant представляет логическую константу.
Скопируйте код кода следующим образом:
Константа общественного класса расширяет выражение {
частное логическое значение;
общественная константа (логическое значение) {
это.значение = значение;
}
@Override
общественное логическое равенство (Object obj) {
if(obj != null && obj экземпляр константы){
return this.value == ((Constant)obj).value;
}
вернуть ложь;
}
@Override
общественный int hashCode() {
верните this.toString().hashCode();
}
@Override
публичная логическая интерпретация (Context ctx) {
возвращаемое значение;
}
@Override
публичная строка toString() {
вернуть новое логическое значение (значение).toString();
}
}
Объект Variable представляет именованную переменную. Код выглядит следующим образом:
Переменная открытого класса расширяет выражение {
частное имя строки;
общедоступная переменная (имя строки) {
это.имя = имя;
}
@Override
общественное логическое равенство (Object obj) {
if(obj != null && obj экземпляр переменной)
{
верните это.имя.равно(
((Переменная)obj).name);
}
вернуть ложь;
}
@Override
общественный int hashCode() {
верните this.toString().hashCode();
}
@Override
публичная строка toString() {
вернуть имя;
}
@Override
публичная логическая интерпретация (Context ctx) {
вернуть ctx.lookup(это);
}
}
Класс And представляет логическую операцию «И», которая представляет собой операцию получения нового логического выражения из двух логических выражений посредством логической операции «И».
Скопируйте код кода следующим образом:
публичный класс и расширяет выражение {
частное выражение влево, вправо;
public And(Выражение слева, Выражение справа){
this.left = слева;
this.right = правильно;
}
@Override
общедоступное логическое равенство (Object obj) {
if(obj != null && obj экземпляр And)
{
вернуть left.equals(((And)obj).left) &&
right.equals(((И)obj).right);
}
вернуть ложь;
}
@Override
общественный int hashCode() {
верните this.toString().hashCode();
}
@Override
публичная логическая интерпретация (Context ctx) {
return left.interpret(ctx) && right.interpret(ctx);
}
@Override
публичная строка toString() {
return "(" + left.toString() + " AND " + right.toString() + ")";
}
}
Класс Or представляет логическую операцию «ИЛИ», которая представляет собой операцию получения нового логического выражения из двух логических выражений посредством логической операции «ИЛИ».
Скопируйте код кода следующим образом:
публичный класс или расширяет выражение {
частное выражение влево, вправо;
public Or(Выражение слева, Выражение справа){
this.left = слева;
this.right = правильно;
}
@Override
общедоступное логическое равенство (Object obj) {
if(obj != null && экземпляр объекта Or)
{
return this.left.equals(((Or)obj).left) && this.right.equals(((Or)obj).right);
}
вернуть ложь;
}
@Override
общественный int hashCode() {
верните this.toString().hashCode();
}
@Override
публичная логическая интерпретация (Context ctx) {
return left.interpret(ctx) || right.interpret(ctx);
}
@Override
публичная строка toString() {
return "(" + left.toString() + " ИЛИ " + right.toString() + ")";
}
}
Класс Not представляет логическую операцию «нет», которая представляет собой операцию получения нового логического выражения из логического выражения посредством логической операции «не». Скопируйте код следующим образом:
публичный класс Не расширяет выражение {
частное выражение exp;
public Not(выражение exp){
this.exp = exp;
}
@Override
общедоступное логическое равенство (Object obj) {
if(obj != null && obj instanceof Not)
{
вернуть exp.equals(
((Не)obj).exp);
}
вернуть ложь;
}
@Override
общественный int hashCode() {
верните this.toString().hashCode();
}
@Override
публичная логическая интерпретация (Context ctx) {
вернуть !exp.interpret(ctx);
}
@Override
публичная строка toString() {
return "(Not " + exp.toString() + ")";
}
}
Класс Context определяет сопоставление переменных с логическими значениями.
Скопируйте код кода следующим образом:
Контекст публичного класса {
частная карта Map<Variable,Boolean> map = new HashMap<Variable,Boolean>();
public void присваивать (переменная var, логическое значение) {
map.put(var, новое логическое значение(значение));
}
публичный логический поиск (переменная var) выдает IllegalArgumentException {
Логическое значение = map.get(var);
если (значение == ноль) {
выбросить новое IllegalArgumentException();
}
возвращаемое значение.booleanValue();
}
}
Класс клиента
Скопируйте код кода следующим образом:
Клиент публичного класса {
public static void main(String[] args) {
Контекст ctx = новый Контекст();
Переменная x = новая переменная («x»);
Переменная y = новая переменная («y»);
Константа c = новая константа (истина);
ctx.assign(х, ложь);
ctx.assign(у, правда);
Выражение exp = new Or(new And(c,x) , new And(y,new Not(x)));
System.out.println("x=" + x.interpret(ctx));
System.out.println("y=" + y.interpret(ctx));
System.out.println(exp.toString() + "=" + exp.interpret(ctx));
}
}
Результаты бега следующие: