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

news2025/7/19 19:58:57

🚀简介

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

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

  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.coloradmin.cn/o/1103473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Java的考研信息查询系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

问题记录2 域名解析问题

上线部署时遇到内网域名解析问题&#xff1a; 内网域名为xxx.cn&#xff0c;在ip为yyy的服务器上&#xff0c;ping&#xff1a;xxx.cn 首先在服务器&#xff1a;yyy /etc/hosts查找缓存记录 cat /etc/hosts 127.0.0.1 VM-4-2-centos VM-4-2-centos 127.0.0.1 localhost.local…

【C+】C++11 —— 线程库

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】C11…

基于SSM的视频播放系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

网络库OKHttp(1)流程+拦截器

序、慢慢来才是最快的方法。 背景 OkHttp 是一套处理 HTTP 网络请求的依赖库&#xff0c;由 Square 公司设计研发并开源&#xff0c;目前可以在 Java 和 Kotlin 中使用。对于 Android App 来说&#xff0c;OkHttp 现在几乎已经占据了所有的网络请求操作。 OKHttp源码官网 版…

JVM垃圾回收算法介绍

堆的分代和区域 &#xff08;年轻代&#xff09;Young Generation&#xff08;eden、s0、s1 space&#xff09; Minor GC &#xff08;老年代&#xff09;Old Generation &#xff08;Tenured space&#xff09; Major GC|| Full GC &#xff08;永久代&#xff09;Permanent…

Qt之自定义插件(单控件,Qt设计师中使用)

文章目录 步骤1.选择项目类型2.设置项目名称3.选择合适的构建套件4.根据实际情况选择插件控件列表6.控件类生成&#xff08;默认勾选项&#xff09;7.构建生成项目及生成库位置&#xff08;默认&#xff09;8.库文件拷贝9.重启Qt查看效果 步骤 1.选择项目类型 如图选择‘其他…

oracle库中数据利用datax工具同步至mysql库

查看oracle版本 $sqlplus aaa/aaaa192.168.1.1/lcfaSQL*Plus: Release 19.0.0.0.0 - Production on Tue Oct 17 15:56:46 2023 Version 19.15.0.0.0Copyright (c) 1982, 2022, Oracle. All rights reserved.Last Successful login time: Tue Oct 17 2023 15:56:03 08:00Conne…

NSS [NISACTF 2022]easyssrf

NSS [NISACTF 2022]easyssrf 先看题目&#xff0c;给了一个输入框 看这提示就知道不是curl了&#xff0c;先file协议读一下flag&#xff0c;file:///flag 不能直接读flag&#xff0c;读个提示文件file:///fl4g 访问一下 <?phphighlight_file(__FILE__); error_reporting(0…

NSS [GWCTF 2019]枯燥的抽奖

NSS [GWCTF 2019]枯燥的抽奖 开题让我猜字符串&#xff0c;这种题目肯定不是猜&#xff0c;应该是类似于php伪随机数。 dirsearch扫他一下。 访问/check.php得到源码。 分析一下代码。 通过PHP伪随机数从字符库$str_long1中选取20个字符组成字符串&#xff0c;返回给我们前十…

EasyCVR视频汇聚平台显示有视频流但无法播放是什么原因?该如何解决?

视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等&#xff0c;视频智能分析平台EasyCVR融合性强、开放度…

BI零售数据分析,当代零售企业的核心竞争力

在数字化转型中&#xff0c;BI智能零售数据分析成为了极其重要的核心竞争力之一。通过对大数据的采集和分析&#xff0c;零售企业可以更好地了解消费者的需求和行为模式&#xff0c;从而做出更准确的决策。例如&#xff0c;通过分析消费者的购物历史、浏览记录等数据&#xff0…

五、WebGPU Vertex Buffers 顶点缓冲区

五、WebGPU Vertex Buffers 顶点缓冲区 在上一篇文章中&#xff0c;我们将顶点数据放入存储缓冲区中&#xff0c;并使用内置的vertex_index对其进行索引。虽然这种技术越来越受欢迎&#xff0c;但向顶点着色器提供顶点数据的传统方式是通过顶点缓冲和属性。 顶点缓冲区就像任…

[Java]0.1+0.2不等于0.3 !!一分钱问题与解决方案

一、原因 原因很简单&#xff0c;计算机存储和计算数组都是用二进制&#xff0c; 而大部分小数转二进制的时候&#xff0c;就丢失精度了。 0.1、0.2、0.3这些小数在二进制里都是循环小数&#xff0c;计算机不可能存储无限循环小数&#xff0c;所以只能截取一部分&#xff0c;导…

Linux网络-UDP/TCP协议详解

Linux网络-UDP/TCP协议详解 2023/10/17 14:32:49 Linux网络-UDP/TCP协议详解 零、前言一、UDP协议二、TCP协议 1、应答机制2、序号机制3、超时重传机制4、连接管理机制 三次握手四次挥手5、理解CLOSE_WAIT状态6、理解TIME_WAIT状态7、流量控制8、滑动窗口 丢包问题9、拥塞控制…

如何使用前端框架(React、Angular、Vue.js等)?该如何选择?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

“小”Bug,大能量

文章目录 简介BUG集&#xff08;持续更新&#xff09;依赖版本不一致配置错误循环依赖内存泄漏并发问题空指针异常依赖版本冲突 总结 简介 在写代码的时候&#xff0c;遇到了一些bug&#xff0c;在当下怎么检查都查不出问题出现在哪&#xff0c;等过几天后突然发现困扰自己的问…

快速自动化处理JavaScript渲染页面的方法

目录 一、使用无头浏览器 二、使用JavaScript渲染引擎 三、使用前端框架工具 随着互联网技术的不断发展&#xff0c;JavaScript已经成为Web开发中不可或缺的一部分。然而&#xff0c;在自动化处理JavaScript渲染页面方面&#xff0c;却常常让开发者感到头疼。本文将介绍一些快…

数仓建设(三)

4) 累积快照事实表 多个业务过程联合分析而构建的事实表&#xff0c;如采购单的流转环节。用于分析事件时间和时间之间的间隔周期。少量的且当前事务型不支持的&#xff0c;如关闭、发货等相关的统计。 4. DWS公共汇总层设计规范 数据仓库的性能是数据仓库建设是否成功的重要标…

从头开始机器学习:逻辑回归

一、说明 本篇实现线性回归的先决知识是&#xff1a;基本线性代数&#xff0c;微积分&#xff08;偏导数&#xff09;、梯度和、Python &#xff08;NumPy&#xff09;&#xff1b;从线性方程入手&#xff0c;逐渐理解线性回归预测问题。 二、逻辑回归简介 我们将以我们在线性回…