博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(十六)—— 解释器模式
阅读量:4583 次
发布时间:2019-06-09

本文共 2959 字,大约阅读时间需要 9 分钟。

模式简介


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

顾名思义,解释器模式就是定义一种语法,并提供一个解释器,客户端可以使用该解释器来解释这个语句来解决问题。例如写文档常用的Markdown语法,可以用-来表示无序列表,用---来表示下划线。通过解释器模式对这种经常使用到的事物,将其定义为一个简单的标识,以便于我们使用。

结构分析


UML类图

971601-20180626185859210-2032902535.png

角色说明

  • AbstractExpression

抽象表达式类,包含一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。

  • TerminalExpression

末端表达式类,实现与在语法中终结符相关联的解释操作,在语句中每个终结符都需要这个实例。

  • NonterminalExpression

非末端表达式类,实现在语法中非末端表达式的解释操作。通常递归的自我调用。

  • Context

上下文,包含解释器之外的一些全局信息。

结构代码

//上下文类public class Context{    }//抽象表达式类abstract class AbstractExpression{    public abstract void Interpret(Context context);}//末端表达式类class TerminalExpression : AbstractExpression{    public override void Interpret(Context context)    {        Console.WriteLine("Called Terminal.Interpret()");    }}//非末端表达式类class NonterminalExpression : AbstractExpression{    public override void Interpret(Context context)    {        Console.WriteLine("Called Nonterminal.Interpret()");    }}//客户端调用class Program{    static void Main(string[] args)    {        Context context = new Context();        var list = new List
(); list.Add(new TerminalExpression()); list.Add(new NonterminalExpression()); list.Add(new TerminalExpression()); list.Add(new TerminalExpression()); foreach (var exp in list) { exp.Interpret(context); } Console.ReadLine(); }}

971601-20180626190051905-1776561601.png

示例分析


本节我们通过解释器模式实现一个简易的Markdown语法,在控制台中输出解释后的内容。首先创建上下文类Context,包含一个Content成员。

class Context{    public string Content { get; set; }}

定义IExpression接口,并通过UnOrderedListExpression和UnderlineExpression子类分别实现无序列表解释器以及下划线解释器。

interface IExpression{    void Interpret(Context context);}class UnOrderedListExpression : IExpression{    public void Interpret(Context context)    {        if (context.Content.Contains("- "))        {            context.Content = context.Content.Replace("- ", "·");        }    }}class UnderlineExpression : IExpression{    public void Interpret(Context context)    {        if (context.Content.Contains("---"))        {            context.Content = context.Content.Replace("---", "__________________________");        }    }}

客户端调用,先向上下文实例的content属性给定内容,并使用UnOrderedListExpression和UnderlineExpression解释器分别对其进行解释,最后输出结果。

class Program{    static void Main(string[] args)    {        Context context = new Context();        context.Content = "- apple\r\n";        context.Content += "- orange\r\n";        context.Content += "- banana\r\n";        context.Content += "---";        List
tree = new List
(); tree.Add(new UnOrderedListExpression()); tree.Add(new UnderlineExpression()); foreach (var exp in tree) { exp.Interpret(context); } Console.WriteLine(context.Content); Console.ReadLine(); }}

程序输出:

971601-20180626200646549-1569378697.png

使用场景


  • 为一些重复出现的问题定义一组简单的语法,便于使用

  • 一个语言需要解释,并将该语言中的句子表示为一个抽象语法树

优点和不足


优点

  • 易于改变和扩展语法

因为使用类来声明表达式,可以使用继承来修改或改变该表达式的行为。

  • 易于实现新的解释表达式方法

不足

  • 容易引起类“爆炸”
  • 对于复杂的语法较难维护

转载于:https://www.cnblogs.com/Answer-Geng/p/9231042.html

你可能感兴趣的文章
多线程同步的几种方法
查看>>
数据结构-冒泡排序
查看>>
关于程序状态字寄存器PSW(Program Status Word)与多核多线程
查看>>
mybatis的缓存
查看>>
java 缓冲流 Buffer
查看>>
7月23号=》261页-265页
查看>>
软考知识点梳理--综合布线
查看>>
Mysql5.6主从热备配置
查看>>
VS2010DebugView捕捉
查看>>
mfix中更改time dependent VTK filename的最大时间步数的容量
查看>>
Windows7安装 docker-compose的过程
查看>>
关于nodeJS多线程的支持,目前看来无法实现,讲解v8的一些东西
查看>>
php递归创建文件夹的两种方法
查看>>
6.新增事件
查看>>
|洛谷|二分|P1182 数列分段Section II
查看>>
少儿编程Scratch第四讲:射击游戏的制作,克隆的奥秘
查看>>
Oracle学习第七课-表连接及其应用
查看>>
Python基础篇【第十三篇】:面向对象
查看>>
bzoj 2465 小球
查看>>
String类
查看>>