c#设计模式-行为型模式 之 解释器模式

🚀简介

给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的 句子。

解释器模式包含以下主要角色

  1. 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主 要包含解释方法 interpret()。
  2. 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结 符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  3. 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法 中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  4. 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有 解释器共享的数据,后面的解释器可以从这里获取这些值。
  5. 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语 法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。

🚀案例

下面是一个简单的解释器模式的C#实现,这个例子中,我们将创建一个IExpression接口和实现了IExpression接口的具体类AddExpressionSubtractExpressionContext是一个解释器上下文类,它将用于存储和管理解释器的状态。

🐤抽象角色AbstractExpression

public interface AbstractExpression
{
    public  int interpret(Context context);

    public string toString();
}

🐤终结符表达式角色

public class Value : AbstractExpression
{
    private int _value;

    public Value(int value)
    {
        _value = value;
    }

    public int interpret(Context context)
    {
        return _value;
    }

    public string toString()
    {
        return _value.ToString();
    }
}

🐤非终结符表达式角色 加减法表达式

/// <summary>
/// 加法
/// </summary>
public class Plus : AbstractExpression
{
    private AbstractExpression _left;
    private AbstractExpression _right;

    public Plus(AbstractExpression left, AbstractExpression right)
    {
        _left = left;
        _right = right;
    }

    public int interpret(Context context)
    {
        return _left.interpret(context) + _right.interpret(context);
    }

    public String toString()
    {
        return "(" + _left.toString() + " + " + _right.toString() + ")";
    }
}

/// <summary>
/// 减法
/// </summary>
public class Minus : AbstractExpression
{
    private AbstractExpression _left;
    private AbstractExpression _right;


    public Minus(AbstractExpression left, AbstractExpression right)
    {
        _left = left;
        _right = right;
    }

    public int interpret(Context context)
    {
        return _left.interpret(context) - _right.interpret(context);
    }

    public string toString()
    {
        return "(" + _left.toString() + " - " + _right.toString() + ")";
    }
}

🐤终结符表达式角色 变量表达式

public class Variable:AbstractExpression

{
    private string _name;

    public Variable(string name)
    {
        _name = name;
    }

    public int interpret(Context context)
    {
        return context.GetValue(this);
    }

    public string toString()
    {
        return _name;
    }
}

🐤环境(Context)角色

public class Context
{
    private Dictionary<Variable, int> map = new Dictionary<Variable, int>();

    public void Assign(Variable var, int value)
    {
        map[var] = value;
    }

    public int GetValue(Variable var)
    {
        int value = map[var];
        return value;
    }
}

🐳测试类

class MyClass
{
    public static void Main(string[] args)
    {
        Context context = new Context();
        Variable a = new Variable("a");
        Variable b = new Variable("b");
        Variable c = new Variable("c");
        Variable d = new Variable("d");
        Variable e = new Variable("e");

        context.Assign(a, 1);
        context.Assign(b, 2);
        context.Assign(c, 3);
        context.Assign(d, 4);
        context.Assign(e, 5);
        AbstractExpression expression = new Minus(new Plus(new Plus(new
            Plus(a, b), c), d), e);
        Console.WriteLine(expression + "= " +
                          expression.interpret(context));
    }
}

👻运行结果!

🚀优缺点

优点:

  1. 易于改变和扩展文法。 由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  2. 实现文法较为容易。 在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
  3. 增加新的解释表达式较为方便。 如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原 有表达式类代码无须修改,符合 "开闭原则"。

缺点:

  1. 对于复杂文法难以维护。 在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
  2. 执行效率较低。 由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而 且代码的调试过程也比较麻烦。

使用场景:

  1. 当语言的文法较为简单,且执行效率不是关键问题时。
  2. 当问题重复出现,且可以用一种简单的语言来进行表达时。
  3. 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。

http://www.niftyadmin.cn/n/5098474.html

相关文章

LiveGBS流媒体平台GB/T28181常见问题-安全控制HTTP接口鉴权勾选流地址鉴权后401Unauthorized如何播放调用接口

LiveGBS流媒体平台GB/T28181常见问题-安全控制HTTP接口鉴权勾选流地址鉴权后401 Unauthorized如何播放调用接口&#xff1f; 1、安全控制1.1、HTTP接口鉴权1.2、流地址鉴权 2、401 Unauthorized2.1、携带token调用接口2.1.1、获取鉴权token2.1.2、调用其它接口2.1.2.1、携带 Co…

网络知识基础一

1.HTTP相应的结构是怎么样的? HTTP响应由三个部分组成: 1:状态码(Status Code):描述了响应的状态。可以用来检查是否成功的完成了请求。请求失败的情况下,状态码可用来找出失败的原因。如果Servlet没有返回状态码,默认会返回成功的状态码HttpServletResponse.SC_OK。 2:…

(Python)MATLAB mat矩阵和Python npy矩阵转换

Python np.ndarray矩阵转换为MATLAB mat文件 import numpy as npimport scipy.io as iomat_path mat_save_pathmat np.zeros([6, 128])io.savemat(mat_path, {name: mat})Python读取MATLAB mat文件 import numpy as np from scipy import iomat io.loadmat(your_mat_file.…

Ubuntu - 查看 IP 地址

要查看 Ubuntu 操作系统中的 IP 地址&#xff0c;可以使用 ip 命令或者 ifconfig 命令。以下是使用这两个命令的示例&#xff1a; 使用 ip 命令&#xff1a; 打开终端。 输入以下命令&#xff1a; ip a 这将显示网络接口信息&#xff0c;包括 IP 地址。通常&#xff0c;IP…

4K壁纸小程序源码 全内容自动采集

全内容自动采集 4K壁纸小程序源码&#xff0c;带流量主。用的都是一个接口&#xff0c;不过这个不知是谁改的&#xff0c;成了LSP版&#xff0c;是真色啊&#xff0c;专搜小姐姐。 4K壁纸&#xff0c;静态壁纸&#xff0c;头像等都有保留&#xff0c;界面广告位很多&#xff0c…

人工智能(pytorch)搭建模型20-基于pytorch搭建文本生成视频的生成对抗网络,技术创新点介绍

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型20-基于pytorch搭建文本生成视频的生成对抗网络&#xff0c;技术创新点介绍&#xff0c;随着人工智能和深度学习技术的飞速发展&#xff0c;文本到视频生成已经成为计算机视觉领域中一个重…

ELK日志分析系统的详细介绍与部署

文章目录 1. ELK的概述1.1 简介1.2 使用ELK的理由1.3 ELK的主要组件1.3.1 Elasticsearch1.3.2 Kibana1.3.3 Logstash1.3.3.1 简介1.3.3.2 Logstash常用相关命令选项 1.3.3.3 Logstash 的输入和输出流1.3.4 Logstash的相关配置文件 1.3.4 Filebeat1.3.4.1 简介1.3.4.2 filebeat …

Windows10系统开启SNMP服务

Windows10系统开启SNMP服务 1、打开控制面板&#xff0c;选择卸载程序2、点击启用或关闭Windows功能3、将SNMP协议开启&#xff08;如果有该内容请直接跳至步骤7&#xff0c;如找不到该协议请继续看步骤4&#xff09;4、找不到步骤3中内容原因&#xff1a;Windwos10 1809后更新…