溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

.Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-05-26 15:51:55 來(lái)源:億速云 閱讀:184 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“.Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“.Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)”吧!

    一、動(dòng)機(jī)(Motivate)

    在軟件構(gòu)建過(guò)程中,如果某一特定領(lǐng)域的問(wèn)題比較復(fù)雜,類(lèi)似的模式不斷重復(fù)出現(xiàn),如果使用普通的編程方式來(lái)實(shí)現(xiàn)將面臨非常頻繁的變化。在這種情況下,將特定領(lǐng)域的問(wèn)題表達(dá)為某種語(yǔ)法規(guī)則下的句子,然后構(gòu)建一個(gè)解釋器來(lái)解釋這樣的句子,從而達(dá)到解決問(wèn)題的目的。

    二、意圖(Intent)

    給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一種解釋器,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。                                 ——《設(shè)計(jì)模式》GoF

    三、結(jié)構(gòu)圖(Structure)

    .Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)

    四、模式的組成

    可以看出,在解釋器模式的結(jié)構(gòu)圖有以下角色:
    (1)、抽象表達(dá)式(AbstractExpression):定義解釋器的接口,約定解釋器的解釋操作。其中的Interpret接口,正如其名字那樣,它是專(zhuān)門(mén)用來(lái)解釋該解釋器所要實(shí)現(xiàn)的功能。
    (2)、終結(jié)符表達(dá)式(Terminal Expression):實(shí)現(xiàn)了抽象表達(dá)式角色所要求的接口,主要是一個(gè)interpret()方法;文法中的每一個(gè)終結(jié)符都有一個(gè)具體終結(jié)表達(dá)式與之相對(duì)應(yīng)。比如有一個(gè)簡(jiǎn)單的公式R=R1+R2,在里面R1和R2就是終結(jié)符,對(duì)應(yīng)的解析R1和R2的解釋器就是終結(jié)符表達(dá)式。
    (3)、非終結(jié)符表達(dá)式(Nonterminal Expression):文法中的每一條規(guī)則都需要一個(gè)具體的非終結(jié)符表達(dá)式,非終結(jié)符表達(dá)式一般是文法中的運(yùn)算符或者其他關(guān)鍵字,比如公式R=R1+R2中,“+”就是非終結(jié)符,解析“+”的解釋器就是一個(gè)非終結(jié)符表達(dá)式。
    (4)、環(huán)境角色(Context):這個(gè)角色的任務(wù)一般是用來(lái)存放文法中各個(gè)終結(jié)符所對(duì)應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環(huán)境角色中,很多情況下我們使用Map來(lái)充當(dāng)環(huán)境角色就足夠了。
    (5)、客戶端(Client):指的是使用解釋器的客戶端,通常在這里將按照語(yǔ)言的語(yǔ)法做的表達(dá)式轉(zhuǎn)換成使用解釋器對(duì)象描述的抽象語(yǔ)法樹(shù),然后調(diào)用解釋操作。

    五、解釋器模式的代碼實(shí)現(xiàn)

    在很多場(chǎng)合都需要把數(shù)字轉(zhuǎn)換成中文,我們就可以使用解釋器來(lái)實(shí)現(xiàn)該功能,把給定的數(shù)字解釋成符合語(yǔ)法規(guī)范的漢字表示法。實(shí)現(xiàn)代碼如下:

    static void Main(string[] args)
    {
        string roman = "五億七千三百零二萬(wàn)六千四百五十二";
        //分解:((五)億)((七千)(三百)(零)(二)萬(wàn))
        //((六千)(四百)(五十)(二))
    
        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);
    }
    // 抽象表達(dá)式
    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();
    
        //這個(gè)可以通用,但是對(duì)于個(gè)位數(shù)字例外,所以用虛方法
        public virtual int GetLength()
        {
            return this.GetPostFix().Length + 1;
        }
    }
    
    //個(gè)位表達(dá)式
    public sealed class GeExpression : Expression
    {
        public override string GetPostFix()
        {
            return "";
        }
    
        public override int Multiplier()
        {
            return 1;
        }
    
        public override int GetLength()
        {
            return 1;
        }
    }
    
    //十位表達(dá)式
    public sealed class ShiExpression : Expression
    {
        public override string GetPostFix()
        {
            return "十";
        }
    
        public override int Multiplier()
        {
            return 10;
        }
    }
    
    //百位表達(dá)式
    public sealed class BaiExpression : Expression
    {
        public override string GetPostFix()
        {
            return "百";
        }
    
        public override int Multiplier()
        {
            return 100;
        }
    }
    
    //千位表達(dá)式
    public sealed class QianExpression : Expression
    {
        public override string GetPostFix()
        {
            return "千";
        }
    
        public override int Multiplier()
        {
            return 1000;
        }
    }
    
    //萬(wàn)位表達(dá)式
    public sealed class WanExpression : Expression
    {
        public override string GetPostFix()
        {
            return "萬(wàn)";
        }
    
        public override int Multiplier()
        {
            return 10000;
        }
    
        public override void Interpreter(Context context)
        {
            if (context.Statement.Length == 0)
            {
                return;
            }
    
            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();
                }
            }
        }
    }
    
    //億位表達(dá)式
    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();
                }
            }
        }
    }
    
    //環(huán)境上下文
    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; }
        }
    }

    六、解釋器模式的實(shí)現(xiàn)要點(diǎn):

    使用Interpreter模式來(lái)表示文法規(guī)則,從而可以使用面向?qū)ο蠹记煞奖愕亍皵U(kuò)展”文法。
    Interpreter模式比較適合簡(jiǎn)單的文法表示,對(duì)于復(fù)雜的文法表示,Interpreter模式會(huì)產(chǎn)生比較大的類(lèi)層次結(jié)構(gòu),需要求助于語(yǔ)法分析生成器這樣的標(biāo)準(zhǔn)工具。

    1、解釋器模式的主要優(yōu)點(diǎn)有:

    1】、易于改變和擴(kuò)展文法。
    2】、每一條文法規(guī)則都可以表示為一個(gè)類(lèi),因此可以方便地實(shí)現(xiàn)一個(gè)簡(jiǎn)單的語(yǔ)言。
    3】、實(shí)現(xiàn)文法較為容易。在抽象語(yǔ)法樹(shù)中每一個(gè)表達(dá)式節(jié)點(diǎn)類(lèi)的實(shí)現(xiàn)方式都是相似的,這些類(lèi)的代碼編寫(xiě)都不會(huì)特別復(fù)雜,還可以通過(guò)一些工具自動(dòng)生成節(jié)點(diǎn)類(lèi)代碼。
    4】、增加新的解釋表達(dá)式較為方便。如果用戶需要增加新的解釋表達(dá)式只需要對(duì)應(yīng)增加一個(gè)新的終結(jié)符表達(dá)式或非終結(jié)符表達(dá)式類(lèi),原有表達(dá)式類(lèi)代碼無(wú)須修改,符合“開(kāi)閉原則”

    2、解釋器模式的主要缺點(diǎn)有:

    1】、對(duì)于復(fù)雜文法難以維護(hù)。在解釋器模式中,每一條規(guī)則至少需要定義一個(gè)類(lèi),因此如果一個(gè)語(yǔ)言包含太多文法規(guī)則,類(lèi)的個(gè)數(shù)將會(huì)急劇增加,導(dǎo)致系統(tǒng)難以管理和維護(hù),此時(shí)可以考慮使用語(yǔ)法分析程序等方式來(lái)取代解釋器模式。
    2】、執(zhí)行效率較低。由于在解釋器模式中使用了大量的循環(huán)和遞歸調(diào)用,因此在解釋較為復(fù)雜的句子時(shí)其速度很慢,而且代碼的調(diào)試過(guò)程也比較麻煩。

    3、在下面的情況下可以考慮使用解釋器模式:

    Interpreter模式的應(yīng)用場(chǎng)合是Interpreter模式應(yīng)用中的難點(diǎn),只有滿足“業(yè)務(wù)規(guī)則頻繁變化,且類(lèi)似的模式不斷重復(fù)出現(xiàn),并且容易抽象為語(yǔ)法規(guī)則的問(wèn)題”才適合使用Interpreter模式。
    1】、當(dāng)一個(gè)語(yǔ)言需要解釋執(zhí)行,并可以將該語(yǔ)言中的句子表示為一個(gè)抽象語(yǔ)法樹(shù)的時(shí)候,可以考慮使用解釋器模式(如XML文檔解釋、正則表達(dá)式等領(lǐng)域)
    2】、一些重復(fù)出現(xiàn)的問(wèn)題可以用一種簡(jiǎn)單的語(yǔ)言來(lái)進(jìn)行表達(dá)。
    3】、一個(gè)語(yǔ)言的文法較為簡(jiǎn)單.
    4】、當(dāng)執(zhí)行效率不是關(guān)鍵和主要關(guān)心的問(wèn)題時(shí)可考慮解釋器模式(注:高效的解釋器通常不是通過(guò)直接解釋抽象語(yǔ)法樹(shù)來(lái)實(shí)現(xiàn)的,而是需要將它們轉(zhuǎn)換成其他形式,使用解釋器模式的執(zhí)行效率并不高。)

    七、.NET 解釋器模式的實(shí)現(xiàn)

    正則表達(dá)式就是一個(gè)典型的解釋器。ASP.NET中,把a(bǔ)spx文件轉(zhuǎn)化為dll時(shí),會(huì)對(duì)html語(yǔ)言進(jìn)行處理,這個(gè)處理過(guò)程也包含了解釋器的模式在里面。Interpreter模式其實(shí)有Composite模式的影子,但它們解決的問(wèn)題是不一樣的。

    感謝各位的閱讀,以上就是“.Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì).Net行為型設(shè)計(jì)模式之解釋器模式怎么實(shí)現(xiàn)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI