大话设计模式:解释器模式

倖福魔咒の 提交于 2019-12-26 01:23:11

一、什么是解释器模式

定义一个语言,定义一个解析器,解析器解释语言

某种繁复的输入可有一定规律抽象为行为,定义语言,使用解释器将这些语言转换为行为,解释器模式提供了评估语言的语法或表达式的方式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

UML图

在这里插入图片描述

AbstractExpression: 抽象表达式,定义一个抽象方法接收输入
TerminalExpression: 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。
NonterminalExpression:——非终结符表达式,文法中的每条规则对应于一个非终结表达式,具体到我们的例子就是加减法规则分别对应到AddExpression和SubExpression两个类。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
Context:上下文,通常包含各个解释器需要的数据,或是公共的功能。

二、适用场景

当有一个语言需要解释执行,并且你可以把该语言中的句子表示为一个抽象的语法树时,比如正则表达式,比如根据用户输入的公式进行加减乘除四则运算

三、优缺点

优点
扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。
缺点
解释器模式会引起类的膨胀:每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。
解释器模式采用递归调用方法:每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,它将导致调试非常复杂。
解释器模式使用了大量的循环和递归:效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。

四、大话中的例子

输入音阶字符转换成音乐标识,一个演奏文本类,负责收集文本,一个表达式抽象类,负责解析,音符类负责解析音符,音阶类负责解析音阶,在客户端输入音乐文本, 调用一个解析器,使用循环不断剥离文本,直到用尽, 每剥离的部分,判断是音阶还是音符,对应解析。

五、我的例子

using System;


namespace InterpreterMode
{
    class Program
    {
        static void Main(string[] args)
        {

            Context context = new Context("3 SB LC MA SC");
            Console.WriteLine(context.Request());
        }
    }

    class Context
    {
        string text;
        public string Text { get => text; set => text = value; }

        public Context(string str)
        {
            text = str;
        }
        AleRamen aleRamen = new Weight();

        public string Request()
        {
            return aleRamen.Interprot(text);
        }

    }

    abstract class AleRamen
    {

        public string Interprot(string context)
        {
            AleRamen aleRamen1 = new Weight();
            AleRamen aleRamen2 = new Category();
            int num = 1;
            string cont = "";
            string[] strs = context.Split(' ');
            try
            {
                num = Convert.ToInt32(strs[0]);
            }
            catch (Exception e)
            {
                num = 1;
            }
            cont += num + "位:";
            for (int i = 0; i < strs.Length; i++)
            {

                char[] chars = strs[i].ToCharArray();

                for (int j = 0; j < chars.Length; j++)
                {
                    cont += aleRamen1.Explain(chars[j]);
                    cont += aleRamen2.Explain(chars[j]);
                }
            }
            return cont;
        }



        public abstract string Explain(Char mychar);
    }

    class Weight : AleRamen
    {
        //  Char[] chars = new Char[] { 'S', 'M', 'L' };


        public override string Explain(Char mychar)
        {
            String text = "";

            switch (mychar)
            {

                case 'S':
                    text = "小份";
                    break;
                case 'M':
                    text = "中份";
                    break;
                case 'L':
                    text = "大份";
                    break;
            }

            return text;
        }

    }

    class Category : AleRamen
    {
        // Char[] chars = new Char[] { 'A', 'B', 'C' };


        public override string Explain(Char mychar)
        {
            String text = "";

            switch (mychar)
            {

                case 'A':
                    text = "招牌拉面 ";
                    break;
                case 'B':
                    text = "豚骨拉面 ";
                    break;
                case 'C':
                    text = "鱼贝拉面 ";
                    break;
            }

            return text;
        }
    }

}

运行结果

在这里插入图片描述
PS:解释器模式一般用不上,一个完整的解析器需要做许多复杂的判断,而那些使用解析器能提高效率的领域,已经有人造好轮子了,我们就不要再瞎折腾。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!