zoukankan      html  css  js  c++  java
  • 设计模式(十六)—— 解释器模式

    模式简介


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

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

    结构分析


    UML类图

    角色说明

    • 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<AbstractExpression>();
            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();
        }
    }
    

    示例分析


    本节我们通过解释器模式实现一个简易的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
    ";
            context.Content += "- orange
    ";
            context.Content += "- banana
    ";
            context.Content += "---";
    
            List<IExpression> tree = new List<IExpression>();
            tree.Add(new UnOrderedListExpression());
            tree.Add(new UnderlineExpression());
    
            foreach (var exp in tree)
            {
                exp.Interpret(context);
            }
    
            Console.WriteLine(context.Content);
            Console.ReadLine();
        }
    }
    

    程序输出:

    使用场景


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

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

    优点和不足


    优点

    • 易于改变和扩展语法

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

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

    不足

    • 容易引起类“爆炸”
    • 对于复杂的语法较难维护
  • 相关阅读:
    mycat安装
    docker注册&打包
    docker的使用场景和背景了解
    解析nohup java -jar xxx &
    透明度百分比和十六进制对应关系
    android get cpu rate
    Cordova插件开发
    VectorDrawable在Android中的配置
    APK反编译后添加日志
    apk重新签名
  • 原文地址:https://www.cnblogs.com/Answer-Geng/p/9231042.html
Copyright © 2011-2022 走看看