Поведенческие паттерны: Интерпретатор (Interpreter) C#
Назначение:
Паттерн Интерпретатор (Interpreter) определяет представление грамматики для заданного языка и интерпретатор предложений этого языка. Как правило, данный шаблон проектирования применяется для часто повторяющихся операций.
Когда использовать Паттерн Interpreter:
Интерпретатор следует использовать когда вам необходимо интерпретировать запись в другом языке и тд. Как один из примеров может служить перевод римских цифр в арабские.
UML схема паттерна "Интерпретатор"
Участники
-
AbstractExpression: определяет интерфейс выражения, объявляет метод
Interpret()
-
TerminalExpression: терминальное выражение, реализует метод
Interpret()
для терминальных символов грамматики. Для каждого символа грамматики создается свой объект TerminalExpression -
NonterminalExpression: нетерминальное выражение, представляет правило грамматики. Для каждого отдельного правила грамматики создается свой объект NonterminalExpression.
-
Context: содержит общую для интерпретатора информацию. Может использоваться объектами терминальных и нетерминальных выражений для сохранения состояния операций и последующего доступа к сохраненному состоянию
-
Client: строит предложения языка с данной грамматикой в виде абстрактного синтаксического дерева, узлами которого являются объекты TerminalExpression и NonterminalExpression
Реализация шаблона "Интерпретатор" на C#:
class MainApp
{
static void Main()
{
string roman = "MMXVIII";
Context context = new Context(roman);
//Строим 'parse tree'
List<Expression> tree = new List<Expression>
{
new ThousandExpression(),
new HundredExpression(),
new TenExpression(),
new OneExpression()
};
//Интерпритатор
foreach (Expression exp in tree)
{
exp.Interpret(context);
}
Console.WriteLine("{0} = {1}",
roman, context.Output);
// Wait for user
Console.ReadKey();
}
}
class Context
{
// Constructor
public Context(string input)
{
Input = input;
}
public string Input { get; set; }
public int Output { get; set; }
}
/// <summary>
/// 'AbstractExpression' класс
/// </summary>
abstract class Expression
{
public void Interpret(Context context)
{
if (context.Input.Length == 0)
return;
if (context.Input.StartsWith(Nine()))
{
context.Output += 9 * Multiplier();
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Four()))
{
context.Output += 4 * Multiplier();
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Five()))
{
context.Output += 5 * Multiplier();
context.Input = context.Input.Substring(1);
}
while (context.Input.StartsWith(One()))
{
context.Output += 1 * Multiplier();
context.Input = context.Input.Substring(1);
}
}
public abstract string One();
public abstract string Four();
public abstract string Five();
public abstract string Nine();
public abstract int Multiplier();
}
/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Тысячные проверки для римской цифры М
/// </remarks>
/// </summary>
class ThousandExpression : Expression
{
public override string One() { return "M"; }
public override string Four() { return " "; }
public override string Five() { return " "; }
public override string Nine() { return " "; }
public override int Multiplier() { return 1000; }
}
/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Сотые проверки для C, CD, D или CM
/// </remarks>
/// </summary>
class HundredExpression : Expression
{
public override string One() { return "C"; }
public override string Four() { return "CD"; }
public override string Five() { return "D"; }
public override string Nine() { return "CM"; }
public override int Multiplier() { return 100; }
}
/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Проверки десяток для X, XL, L и XC
/// </remarks>
/// </summary>
class TenExpression : Expression
{
public override string One() { return "X"; }
public override string Four() { return "XL"; }
public override string Five() { return "L"; }
public override string Nine() { return "XC"; }
public override int Multiplier() { return 10; }
}
/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Проверки едениц для I, II, III, IV, V, VI, VI, VII, VIII, IX
/// </remarks>
/// </summary>
class OneExpression : Expression
{
public override string One() { return "I"; }
public override string Four() { return "IV"; }
public override string Five() { return "V"; }
public override string Nine() { return "IX"; }
public override int Multiplier() { return 1; }
}