陈巧倩

设计模式-解释器模式

· 362 words · 2 minutes to read
Categories: CSharp
Tags: Design Pattern

Interpreter解释器模式属于行为型设计模式,该模式定义其语法的表示以及使用该表示来解释该语言中的句子的解释器。

Design Pattern:Interpreter 🔗

基本介绍 🔗

构成 🔗

  • Abstract Expression:抽象表达式类,定义解释器的接口,约定解释器的解释操作,其中定义Interpret接口,专门用来解释该解释器所要实现的功能。
  • Terminal Expression:终端表达式类,实现了抽象表达式类所要求的接口,每一个终端符都有一个具体终端表达式与之相对应。例如:A = A1+A2,A1和A2为终端运算符。
  • Nonterminal Expression:非终端表达式类,一般是语法中的运算符或者其他关键字,比如公式A=A1+A2中,“+”就是非终端符,解析“+”的解释器就是一个非终端符表达式。
  • Context:上下文类,用来存放语法中各个终端符所对应的具体值,提供给解释器进行解析和解释的输入以及从中获得的输出,例如:A=A1+A2,A1赋值10,给A2赋值20。
  • Client:解释器客户端类,构建一个抽象语法树,表示语法定义的语言中的特定句子。抽象语法树由 Nonterminal Expression 和 Terminal Expression 类的实例组装而成。

优点 🔗

  • 较高的可扩展性和可修改性,每个语法规则都会自动继承父类的属性和方法。通过这种方式,可以向子类添加更改和扩展,以增量方式修改、扩展和更改语法规则。
  • 语法规则易于实现: 此模式将语法类表示为语法树,其中每个节点表示一个语法规则。

缺点 🔗

  • 对于复杂语法难以实现。
  • 执行效率较低。

实例 🔗

C#中解释器模式的实例,我准备使用解释器模式实现一套加减乘除运算。

/// <summary>
/// 抽象表达式类
/// </summary>
public abstract class Expression
{
    public abstract int Interpret(Context context);
}
/// <summary>
/// 终端表达式类 数字常量
/// </summary>
public class NumberExpression : Expression
{
    private readonly int _number;
    public NumberExpression(int number)
    {
        _number = number;
    }
    public override int Interpret(Context context)
    {
        return _number;
    }
}
/// <summary>
/// 非终端表达式类 加
/// </summary>
public class AddExpression : Expression
{
    private readonly Expression _numberExpression1;
    private readonly Expression _numberExpression2;
    public AddExpression(Expression number1, Expression number2)
    {
        _numberExpression1 = number1;
        _numberExpression2 = number2;
    }
    public override int Interpret(Context context)
    {
        return _numberExpression1.Interpret(context) + _numberExpression2.Interpret(context);
    }
}
/// <summary>
/// 非终端表达式类 减
/// </summary>
public class SubtractExpression : Expression
{
    private readonly Expression _numberExpression1;
    private readonly Expression _numberExpression2;
    public SubtractExpression(Expression number1, Expression number2)
    {
        _numberExpression1 = number1;
        _numberExpression2 = number2;
    }
    public override int Interpret(Context context)
    {
        return _numberExpression1.Interpret(context) - _numberExpression2.Interpret(context);
    }
}
/// <summary>
/// 非终端表达式类 乘
/// </summary>
public class MultiplyExpression : Expression
{
    private readonly Expression _numberExpression1;
    private readonly Expression _numberExpression2;
    public MultiplyExpression(Expression number1, Expression number2)
    {
        _numberExpression1 = number1;
        _numberExpression2 = number2;
    }
    public override int Interpret(Context context)
    {
        return _numberExpression1.Interpret(context) * _numberExpression2.Interpret(context);
    }
}
/// <summary>
/// 非终端表达式类 除
/// </summary>
public class DivideExpression : Expression
{
    private readonly Expression _numberExpression1;
    private readonly Expression _numberExpression2;
    public DivideExpression(Expression number1, Expression number2)
    {
        _numberExpression1 = number1;
        _numberExpression2 = number2;
    }
    public override int Interpret(Context context)
    {
        return _numberExpression1.Interpret(context) / _numberExpression2.Interpret(context);
    }
}
/// <summary>
/// 上下文类
/// </summary>
public class Context
{
    private readonly Dictionary<string, int> _numbers;
    public Context()
    {
        _numbers = new Dictionary<string, int>();
    }
    public void SetNumber(string key, int number)
    {
        _numbers.Add(key, number);
    }
    public int GetNumber(string key)
    {
        if (_numbers.ContainsKey(key))
            return _numbers[key];
        return 0;
    }
}

实际运行:

public class Client
{
    public void Main()
    {
        var context = new Context();
        context.SetNumber("Number1", 2);
        context.SetNumber("Number2", 3);

        var expression = new AddExpression
            (
            new NumberExpression(10),
            new MultiplyExpression
            (
                new NumberExpression(20),
                new AddExpression
                (
                    new NumberExpression(context.GetNumber("Number1")),
                    new NumberExpression(context.GetNumber("Number2"))
                )
            )
        );
        expression.Interpret(context);
    }
}

结论 🔗

搬砖愉快!