设计模式(23)——解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

接下来描述一个将中文数字转化为阿拉伯数字的例子

先定义一个抽象表达式

public abstract class Expression
{
    protected Dictionary<string, int> table = new Dictionary<string, int>(9);

    protected 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);
    }

    public virtual void Interpreter(Context context)
    {
        if (context.Statement.Length == 0)
        {
            return;
        }

        foreach (string key in table.Keys)
        {
            int value = table[key];

            if (context.Statement.EndsWith(key + GetPostFix()))
            {
                context.Data += value * this.Multiplier();
                context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
            }
            if (context.Statement.EndsWith("零"))
            {
                context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
            }
        }
    }

    public abstract string GetPostFix();

    public abstract int Multiplier();

    //这个可以通用,但是对于个位万位亿位数字例外,所以用虚方法
    public virtual int GetLength()
    {
        return this.GetPostFix().Length + 1;
    }
}

再实现个位、十位、百位、千位、万位、亿位的表达式

//个位表达式
public sealed class GeExpression : Expression
{
    public override string GetPostFix()
    {
        return "";
    }

    public override int Multiplier()
    {
        return 1;
    }

    public override int GetLength()
    {
        return 1;
    }
}

//十位表达式
public sealed class ShiExpression : Expression
{
    public override string GetPostFix()
    {
        return "十";
    }

    public override int Multiplier()
    {
        return 10;
    }
}

//百位表达式
public sealed class BaiExpression : Expression
{
    public override string GetPostFix()
    {
        return "百";
    }

    public override int Multiplier()
    {
        return 100;
    }
}

//千位表达式
public sealed class QianExpression : Expression
{
    public override string GetPostFix()
    {
        return "千";
    }

    public override int Multiplier()
    {
        return 1000;
    }
}

//万位表达式
public sealed class WanExpression : Expression
{
    public override string GetPostFix()
    {
        return "万";
    }

    public override int Multiplier()
    {
        return 10000;
    }

    public override void Interpreter(Context context)
    {
        ArrayList tree = new ArrayList();

        tree.Add(new GeExpression());
        tree.Add(new ShiExpression());
        tree.Add(new BaiExpression());
        tree.Add(new QianExpression());

        foreach (string key in table.Keys)
        {
            if (context.Statement.EndsWith(GetPostFix()))
            {
                int temp = context.Data;
                context.Data = 0;

                context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());

                foreach (Expression exp in tree)
                {
                    exp.Interpreter(context);
                }
                context.Data = temp + context.Data * this.Multiplier();
            }
        }
    }
    public override int GetLength()
    {
        return 1;
    }
}

//亿位表达式
public sealed class YiExpression : Expression
{
    public override string GetPostFix()
    {
        return "亿";
    }

    public override int Multiplier()
    {
        return 100000000;
    }

    public override void Interpreter(Context context)
    {
        ArrayList tree = new ArrayList();

        tree.Add(new GeExpression());
        tree.Add(new ShiExpression());
        tree.Add(new BaiExpression());
        tree.Add(new QianExpression());

        foreach (string key in table.Keys)
        {
            if (context.Statement.EndsWith(GetPostFix()))
            {
                int temp = context.Data;
                context.Data = 0;
                context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());

                foreach (Expression exp in tree)
                {
                    exp.Interpreter(context);
                }
                context.Data = temp + context.Data * this.Multiplier();
            }
        }
    }
    public override int GetLength()
    {
        return 1;
    }
}

环境上下文

public sealed class Context
{
    private string _statement;
    private int _data;

    public Context(string statement)
    {
        this._statement = statement;
    }

    public string Statement
    {
        get { return this._statement; }
        set { this._statement = value; }
    }

    public int Data
    {
        get { return this._data; }
        set { this._data = value; }
    }
}

调用

class Program
{
    static void Main(string[] args)
    {
        string roman = "五亿七千三百零二万六千四百五十二";
        //分解:((五)亿)((七千)(三百)(零)(二)万)
        //((六千)(四百)(五十)(二))

        Context context = new Context(roman);
        ArrayList tree = new ArrayList();

        tree.Add(new GeExpression());
        tree.Add(new ShiExpression());
        tree.Add(new BaiExpression());
        tree.Add(new QianExpression());
        tree.Add(new WanExpression());
        tree.Add(new YiExpression());

        foreach (Expression exp in tree)
        {
            exp.Interpreter(context);
        }

        Console.Write(context.Data);

        Console.Read();
    }
}

结果

573026452

类图

在这里插入图片描述

优点与缺点

解释器模式的优点:

  • 可扩展性比较好,灵活。
  • 增加了新的解释表达式的方式。
  • 易于实现文法。

解释器模式的缺点:

  • 执行效率比较低,可利用场景比较少。
  • 对于复杂的文法比较难维护。

本文主要借鉴了《Gof设计模式》与C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值