• 设计模式学习笔记解释器模式


    概述:                                                                                                      

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

    适用场合:                                                                                                 

    当一个语言需要解释执行,并且你可以将该语句中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好。

    1.该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。

    2.效率不是一个关键问题,最高效的解释器通常不是通过直接解析语法分析树实现的,而是首先将他们转换成另一种形式。

    类图:                                                                                                      

    代码示例:                                                                                                

    1.抽象表达式类

        /// <summary>
    /// 声明一个抽象的解释操作,这个接口为抽象语树中所有节点共享
    /// </summary>
    abstract class AbstractExpression
    {
    public abstract void Interpret(Context context);
    }

    2.全局信息类

        /// <summary>
    /// 包含解释器之外的一些全局信息
    /// </summary>
    class Context
    {
    private string input;
    public string Input
    {
    get { return input; }
    set { input = value; }
    }
    private string output;
    public string Output
    {
    get { return output; }
    set { output = value; }
    }
    }

    3.终结符表达式类

        /// <summary>
    /// 终结符表达式,实现与文法中的终结符相关联的解释操作。
    /// 实现抽象表达式中所要求的接口,主要是一个interpret方法,
    /// 文中每一个终结符都有一个具体中介表达式与之相对应。
    /// </summary>
    class TerminalExpression:AbstractExpression
    {
    public override void Interpret(DesignPatternLab.InterpreterPackage.Context context)
    {
    Console.WriteLine(
    "终端解释器");
    }
    }

    4.非终结符表达式类

        /// <summary>
    /// 非终结符表达式,为文法的非终结符实现解释操作。对文法中每一条规则
    /// 都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret
    /// 方法实现解释操作,解释操作以递归的方式调用实例变量
    /// </summary>
    class NonterminalExpression:AbstractExpression
    {
    public override void Interpret(Context context)
    {
    Console.WriteLine(
    "非终端解释器");
    }
    }

    5.客户端调用

            /// <summary>
    /// 测试解释器模式
    /// </summary>
    static void TestInterpret()
    {
    DesignPatternLab.InterpreterPackage.Context context
    = new InterpreterPackage.Context();
    IList
    <AbstractExpression> list = new List<AbstractExpression>();
    list.Add(
    new TerminalExpression());
    list.Add(
    new NonterminalExpression());
    list.Add(
    new NonterminalExpression());
    list.Add(
    new TerminalExpression());

    foreach(AbstractExpression exp in list)
    {
    exp.Interpret(context);
    }
    Console.Read();
    }

    小结:                                                                                                      

    解释器模式一般应用在正则表达式应用,浏览器程序上,下面列举一个汉字数字大小写转换的例子加深理解

    汉字数字大小写转换

    View Code
        /// <summary>
    /// 抽象表达式角色
    /// </summary>
    public abstract class Expression
    {
    /// <summary>
    /// 汉字数字与阿拉伯数字数字的对应字典
    /// </summary>
    protected Dictionary<string, int> table = new Dictionary<string, int>(9);
    public Expression()
    {
    table.Add(
    "", 1);
    table.Add(
    "", 2);
    table.Add(
    "", 3);
    table.Add(
    "", 4);
    table.Add(
    "", 5);
    table.Add(
    "", 6);
    table.Add(
    "", 7);
    table.Add(
    "", 8);
    table.Add(
    "", 9);
    }
    /// <summary>
    /// 所有的具体表达式角色都需要实现的抽象方法
    /// 这个方法为虚方法,并非抽象方法,为了代码复用
    /// </summary>
    /// <param name="context">环境角色</param>
    public virtual void Interpret(ContextcnNum context)
    {
    //如果要处理的字符串长度为0则返回
    if (context.statement.Length == 0)
    {
    return;
    }
    foreach (string key in table.Keys)
    {
    int value = table[key];
    if (context.statement.EndsWith(key + GetPostifix()))
    {
    context.data
    += value * Multiplier();
    context.statement
    = context.statement.Substring(0, context.statement.Length - this.GetLength());
    break;
    }

    if (context.statement.EndsWith(""))
    {
    context.statement
    = context.statement.Substring(0, context.statement.Length - 1);
    break;
    }
    if (context.statement.Length == 0)
    {
    return;
    }
    }
    }
    /// <summary>
    /// 取汉字数字单位
    /// 个位数为空
    /// 十位数为十
    /// 百位数为百
    /// 千位数为千
    /// </summary>
    /// <returns></returns>
    public abstract string GetPostifix();
    /// <summary>
    /// 例如:个位上数字为2,则最后为2*1
    /// 例如:百位上数字为3,则表示3*10
    /// </summary>
    /// <returns></returns>
    public abstract int Multiplier();
    /// <summary>
    /// 例如:个位的长度为一位
    /// 例如数字三十,表示两位
    /// 例如四百,表示两位
    /// </summary>
    /// <returns></returns>
    public virtual int GetLength()
    {
    return this.GetPostifix().Length + 1;
    }
    }

    /// <summary>
    /// 终结符表达式角色
    /// 如果能换算成数字则直接换算后返回
    /// </summary>
    class NumTerminalExpression : Expression
    {
    /// <summary>
    /// 重写解释方法
    /// </summary>
    /// <param name="context">环境角色</param>
    public override void Interpret(ContextcnNum context)
    {
    int i = 0;
    try
    {
    i
    = int.Parse(context.statement);
    //如果是数字则说明能够直接转换
    //也就是说用不到非终结表达式角色
    context.statement = "";
    context.data
    = i;
    }
    catch
    {
    //说明输入的是汉字数字,不做任何处理
    }
    }
    public override string GetPostifix()
    {
    return "";
    }
    public override int Multiplier() { return 1; }
    }

    /// <summary>
    /// 非终结表达式角色
    /// 解释个位数
    /// </summary>
    public class NonterminalOneExpression : Expression
    {
    public override string GetPostifix()
    {
    return "";
    }
    public override int Multiplier() { return 1; }
    public override int GetLength()
    {
    return 1;
    }
    }
    /// <summary>
    /// 非终结表达式角色
    /// 解释十位数
    /// </summary>
    public class NonterminalTenExpression : Expression
    {
    public override string GetPostifix()
    {
    return "";
    }
    public override int Multiplier() { return 10; }
    public override int GetLength()
    {
    return 2;
    }
    }
    /// <summary>
    /// 非终结表达式角色
    /// 解释百位数
    /// </summary>
    public class NonterminalHundredExpression : Expression
    {
    public override string GetPostifix()
    {
    return "";
    }
    public override int Multiplier() { return 100; }
    public override int GetLength()
    {
    return 2;
    }
    }
    /// <summary>
    /// 非终结表达式角色
    /// 解释千位数
    /// </summary>
    public class NonterminalThousandExpression : Expression
    {
    public override string GetPostifix()
    {
    return "";
    }
    public override int Multiplier() { return 1000; }
    public override int GetLength()
    {
    return 2;
    }
    }
    /// 环境角色
    /// </summary>
    public class ContextcnNum
    {
    /// <summary>
    /// 汉字表示的数字
    /// </summary>
    public string statement
    {
    get;
    set;
    }
    /// <summary>
    /// 阿拉伯数字
    /// </summary>
    public int data
    {
    get;
    set;
    }
    /// <summary>
    /// 构造函数
    /// 接受一个汉字表达式数字
    /// </summary>
    /// <param name="statement">汉字表达式数字</param>
    public ContextcnNum(string statement)
    {
    this.statement = statement;
    }
    }

    /// <summary>
    /// 测试解释器模式例子
    /// </summary>
    static void TestInterpretSample()
    {
    string roman = "伍千肆百参拾贰"; //5432
    ContextcnNum context = new ContextcnNum(roman);
    //构造抽象语法树
    ArrayList tree = new ArrayList();
    //加入终结符表达式
    //如果能直接转换成数字则直接返回
    tree.Add(new NumTerminalExpression());
    //非终结符,处理个位数
    tree.Add(new NonterminalOneExpression());
    //非终结符,处理十位数
    tree.Add(new NonterminalTenExpression());
    //非终结符,处理百位数
    tree.Add(new NonterminalHundredExpression());
    //非终结器,处理千位数
    tree.Add(new NonterminalThousandExpression());
    //对抽象语法树的每个枝节进行解释操作
    foreach (Expression exp in tree)
    {
    exp.Interpret(context);
    }
    Console.WriteLine(
    "{0} = {1}", roman, context.data);
    Console.Read();
    }

      

  • 相关阅读:
    [POJ 1050]To the Max
    P1678 烦恼的高考志愿
    P1873 砍树
    P1102 A-B 数对
    P6771 [USACO05MAR]Space Elevator 太空电梯
    P2347 砝码称重
    P1832 A+B Problem(再升级)
    P1679 神奇的四次方数
    P1877 [HAOI2012]音量调节
    P1049 装箱问题
  • 原文地址:https://www.cnblogs.com/jqbird/p/2169566.html
Copyright © 2020-2023  润新知