設計模式之直譯器模式

安全劍客發表於2020-09-22

前言

直譯器模式和介面卡模式有些異曲同工之妙。介面卡是用介面使之相容,直譯器是用語言來解釋句子。

直譯器模式

給定義一個語言,定義它的文法(法規)的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。
也就是說將一句話,轉變成實際的命令程式執行。

情景

我們都熟悉的程式語言。人們要控制計算機一定要通過計算機語言向計算機發出命令,否則計算機時不會懂得人們的指令的。這裡的程式語言就相當於時直譯器。
YUYAN

優缺點

優點:

  1. 很容易的改變和擴充套件文法,因為該模式使用類來表示文法規則,你可使用繼承來改變或擴充套件該文法。
  2. 容易實現文法,因為定義抽象語法樹中各個節點的類的實現大體類似

缺點:

  1. 為文法中的每一條規則至少定義了一個類,因此包含許多規則的文法可能難以管理和維護。
  2. 當文法非常複雜時,建議使用其他的技術如語法分析程式或編譯器來處理。

應用

正規表示式,瀏覽器。只要是可以用語言來描述的,都可以。

它需要解決的是:如果一種特定型別的問題發生的頻率足夠高,那麼可能就值得將該問題的各個例項表述為一個簡單語言中的句子。這樣就可以構建一個直譯器,該直譯器通過解釋這些句子來解決該問題。

程式碼展示

音樂直譯器程式:

演奏內容類:

//演奏內容
    class PlayContext
    {
        //演奏文字
        private string text;
        public string PlayText
        {
            get { return text; }
            set { text = value; }
        }
    }

表示式類:(抽象表示式——–宣告一個抽象的解釋操作AbstractExpression)

abstract  class Expression
    {
        //直譯器
        public void Interpret(PlayContext context)
        {
            if (context.PlayText.Length == 0)
            {
                return;
            }
            else 
            {
                string playKey = context.PlayText.Substring(0, 1);//將當前的演奏文字第一條命令獲得命令字母和其引數值
                context .PlayText = context .PlayText .Substring (2);
                double playValue = Convert .ToDouble (context .PlayText .Substring (0,context .PlayText .IndexOf (" ")));

                //獲得playkey和 playvalue後將其從演奏文字中移除
                context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ") + 1);

                Excute(playKey, playValue);
            }
        }

        //執行----------抽象方法執行,不同的文法子類有不同的執行處理
        public abstract void Excute(string key, double value);
    }

音符類:(終結符表示式—-實現解釋操作terminal)

//音符類
    class Note:Expression 
    {
        public override void Excute(string key, double value)
        {
            string note = "";
            switch (key)
            {
                    //如果獲得的key是C,則演奏1(do)
                case "C":
                    note = "1";
                    break;

                case "D":
                    note = "2";
                    break;

                case "E":
                    note = "3";
                    break;

                case "F":
                    note = "4";
                    break;

                case "G":
                    note = "5";
                    break;

                case "A":
                    note = "6";
                    break;

                case "B":
                    note = "7";
                    break;
            }
            Console.WriteLine("{0}",note );
        }
    }






    //音階類
    class Scale:Expression 
    {
        public override void Excute(string key, double value)
        {
            string scale = "";
            switch (Convert.ToInt32(value))
            {
                case 1:
                    scale = "低音";
                    break;

                case 2:
                    scale = "中音";
                    break;

                case 3:
                    scale = "高音";
                    break;
            }

            Console.WriteLine("{0}",scale );
        }
    }


    //這裡還可以新增速度類等

客戶端程式碼:

class Program
    {
        static void Main(string[] args)
        {
            PlayContext context = new PlayContext();

            //音樂--上海灘
            Console.WriteLine("上海灘");

            //播放的音符,音階,及旋律拍子-----O 2指中音區的音符 ;E代表了3這個音;0.5指半拍。

            context.PlayText = "O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ";
            Expression expression = null;
            try
            {
                while (context.PlayText.Length > 0)
                {
                    string str = context.PlayText.Substring(0, 1);
                    switch (str)
                    {
                        case "O": //首欄位為O時,表示式例項化為音階
                            expression = new Scale();
                            break;
                        case "C":     //首字母為CDEFGAB時,例項化音符
                        case "D":
                        case "E":
                        case "F":
                        case "G":
                        case "A":
                        case "B":
                        case "P":  //休止符
                            expression = new Note();
                            break;
                    }
                    expression.Interpret(context);
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message );
            }
            Console.ReadLine();
        }

    }

圖片解釋:
O 2指中音區的音符 ;E代表了3這個音;0.5指半拍,3指三拍

context.PlayText = “O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 “;

音符

錯誤解決

錯誤

這裡寫圖片描述

解決:
將3後面加上一個空格

解決

後記

今天又體驗了一把學習音樂的好處啊~

相關文章