您的位置:首页 > 编程语言 > C#

Design Pattern - Interpreter(C#)

2010-12-02 20:12 525 查看

Definition

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Participants

    The classes and/or objects participating in this pattern are:

AbstractExpression  (Expression)
Declares an interface for executing an operation

TerminalExpression  (ThousandExpression, HundredExpression, TenExpression, OneExpression)
Implements an Interpret operation associated with terminal symbols in the grammar.
An instance is required for every terminal symbol in the sentence.

NonterminalExpression  (not used)
One such class is required for every rule R ::= R1R2...Rn in the grammar
Maintains instance variables of type AbstractExpression for each of the symbols R1 through Rn.
Implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the variables representing R1 through Rn.

Context  (Context)
Contains information that is global to the interpreter

Client  (InterpreterApp)
Builds (or is given) an abstract syntax tree representing a particular sentence in the language that the grammar defines. The abstract syntax tree is assembled from instances of the NonterminalExpression
and TerminalExpression classes
Invokes the Interpret operation

Sample Code in C#

This
structural code demonstrates the Interpreter patterns, which using a defined grammer, provides the interpreter that processes parsed statements.

// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Chimomo's Company" file="Program.cs">
// Respect the work.
// </copyright>
// <summary>
// Structural Interpreter Design Pattern.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace CSharpLearning
{
using System;
using System.Collections;

/// <summary>
/// Startup class for Structural Interpreter Design Pattern.
/// </summary>
internal static class Program
{
#region Methods

/// <summary>
/// Entry point into console application.
/// </summary>
private static void Main()
{
var context = new Context();

// Usually a tree
var list = new ArrayList
{
new TerminalExpression(),
new NonterminalExpression(),
new TerminalExpression(),
new TerminalExpression()
};

// Interpret
foreach (AbstractExpression exp in list)
{
exp.Interpret(context);
}
}

#endregion
}

/// <summary>
/// The 'Context' class
/// </summary>
internal class Context
{
}

/// <summary>
/// The 'AbstractExpression' abstract class
/// </summary>
internal abstract class AbstractExpression
{
#region Public Methods and Operators

/// <summary>
/// The interpret.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
public abstract void Interpret(Context context);

#endregion
}

/// <summary>
/// The 'TerminalExpression' class
/// </summary>
internal class TerminalExpression : AbstractExpression
{
#region Public Methods and Operators

/// <summary>
/// The interpret.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
public override void Interpret(Context context)
{
Console.WriteLine("Called Terminal.Interpret()");
}

#endregion
}

/// <summary>
/// The 'NonterminalExpression' class
/// </summary>
internal class NonterminalExpression : AbstractExpression
{
#region Public Methods and Operators

/// <summary>
/// The interpret.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
public override void Interpret(Context context)
{
Console.WriteLine("Called Nonterminal.Interpret()");
}

#endregion
}
}

// Output:
/*
Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()
*/

This
real-world code demonstrates the Interpreter pattern which is used to convert a Roman numeral to a decimal.

// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Chimomo's Company" file="Program.cs">
// Respect the work.
// </copyright>
// <summary>
// Real-World Interpreter Design Pattern.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace CSharpLearning
{
using System;
using System.Collections.Generic;

/// <summary>
/// Startup class for Real-World Interpreter Design Pattern.
/// </summary>
internal static class Program
{
#region Methods

/// <summary>
/// Entry point into console application.
/// </summary>
private static void Main()
{
const string Roman = "MCMXXVIII";
var context = new Context(Roman);

// Build the 'parse tree'
var tree = new List<Expression>
{
new ThousandExpression(),
new HundredExpression(),
new TenExpression(),
new OneExpression()
};

// Interpret
foreach (Expression exp in tree)
{
exp.Interpret(context);
}

Console.WriteLine("{0} = {1}", Roman, context.Output);
}

#endregion
}

/// <summary>
/// The 'Context' class
/// </summary>
internal class Context
{
// Constructor
#region Constructors and Destructors

/// <summary>
/// Initializes a new instance of the <see cref="Context"/> class.
/// </summary>
/// <param name="input">
/// The input.
/// </param>
public Context(string input)
{
this.Input = input;
}

#endregion

// Gets or sets input
#region Public Properties

/// <summary>
/// Gets or sets the input.
/// </summary>
public string Input { get; set; }

// Gets or sets output

/// <summary>
/// Gets or sets the output.
/// </summary>
public int Output { get; set; }

#endregion
}

/// <summary>
/// The 'AbstractExpression' class
/// </summary>
internal abstract class Expression
{
#region Public Methods and Operators

/// <summary>
/// The five.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public abstract string Five();

/// <summary>
/// The four.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public abstract string Four();

/// <summary>
/// The interpret.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
public void Interpret(Context context)
{
if (context.Input.Length == 0)
{
return;
}

if (context.Input.StartsWith(this.Nine()))
{
context.Output += 9 * this.Multiplier();
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(this.Four()))
{
context.Output += 4 * this.Multiplier();

context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(this.Five()))
{
context.Output += 5 * this.Multiplier();
context.Input = context.Input.Substring(1);
}

while (context.Input.StartsWith(this.One()))
{
context.Output += 1 * this.Multiplier();
context.Input = context.Input.Substring(1);
}
}

/// <summary>
/// The multiplier.
/// </summary>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
public abstract int Multiplier();

/// <summary>
/// The nine.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public abstract string Nine();

/// <summary>
/// The one.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public abstract string One();

#endregion
}

/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Thousand checks for the Roman Numeral M
/// </remarks>
/// </summary>
internal class ThousandExpression : Expression
{
#region Public Methods and Operators

/// <summary>
/// The five.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Five()
{
return " ";
}

/// <summary>
/// The four.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Four()
{
return " ";
}

/// <summary>
/// The multiplier.
/// </summary>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
public override int Multiplier()
{
return 1000;
}

/// <summary>
/// The nine.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Nine()
{
return " ";
}

/// <summary>
/// The one.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string One()
{
return "M";
}

#endregion
}

/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Hundred checks C, CD, D or CM
/// </remarks>
/// </summary>
internal class HundredExpression : Expression
{
#region Public Methods and Operators

/// <summary>
/// The five.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Five()
{
return "D";
}

/// <summary>
/// The four.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Four()
{
return "CD";
}

/// <summary>
/// The multiplier.
/// </summary>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
public override int Multiplier()
{
return 100;
}

/// <summary>
/// The nine.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Nine()
{
return "CM";
}

/// <summary>
/// The one.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string One()
{
return "C";
}

#endregion
}

/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// Ten checks for X, XL, L and XC
/// </remarks>
/// </summary>
internal class TenExpression : Expression
{
#region Public Methods and Operators

/// <summary>
/// The five.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Five()
{
return "L";
}

/// <summary>
/// The four.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Four()
{
return "XL";
}

/// <summary>
/// The multiplier.
/// </summary>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
public override int Multiplier()
{
return 10;
}

/// <summary>
/// The nine.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Nine()
{
return "XC";
}

/// <summary>
/// The one.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string One()
{
return "X";
}

#endregion
}

/// <summary>
/// A 'TerminalExpression' class
/// <remarks>
/// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
/// </remarks>
/// </summary>
internal class OneExpression : Expression
{
#region Public Methods and Operators

/// <summary>
/// The five.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Five()
{
return "V";
}

/// <summary>
/// The four.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Four()
{
return "IV";
}

/// <summary>
/// The multiplier.
/// </summary>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
public override int Multiplier()
{
return 1;
}

/// <summary>
/// The nine.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string Nine()
{
return "IX";
}

/// <summary>
/// The one.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public override string One()
{
return "I";
}

#endregion
}
}

// Output:
/*
MCMXXVIII = 1928
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息