24_直譯器模式

野码發表於2024-03-17

直譯器模式是一種行為設計模式,它透過定義一個語言的文法規則,並且根據規則解釋和執行對應的語言表示式。

在直譯器模式中,透過定義抽象表示式(Abstract Expression)和具體表示式(Concrete Expression)來表示語言中的各種表示式。抽象表示式定義了表示式的解釋方法,而具體表示式則實現瞭解釋方法。

直譯器模式包含以下幾個角色:

  1. 抽象表示式(Abstract Expression):定義了表示式解釋方法的介面。

  2. 終結符表示式(Terminal Expression):實現瞭解釋方法,表示語言中的終結符表示式。

  3. 非終結符表示式(Non-terminal Expression):實現瞭解釋方法,表示語言中的非終結符表示式。

  4. 環境(Context):包含了直譯器需要的資訊,負責儲存和傳遞變數的值等。

直譯器模式的工作流程如下:

  1. 定義語言的文法規則,並將每個規則抽象成一個抽象表示式。

  2. 實現具體表示式,來表示語言中的各種表示式。

  3. 根據具體情況,建立具體表示式的例項,並將其組合成一個直譯器樹。

  4. 呼叫直譯器樹的解釋方法,對語言表示式進行解釋和執行。

直譯器模式的優點包括:

  1. 可擴充套件性好,可以動態地新增新的表示式。

  2. 可以靈活地改變文法規則和解釋方法。

  3. 可以方便地實現對語言表示式的解釋和執行。

直譯器模式適用於以下情況:

  1. 有一個簡單的語言,需要解釋和執行其中的表示式。

  2. 表示式的數量和複雜度有限,且經常需要進行修改和擴充套件。

總之,直譯器模式是一種透過定義文法規則來解釋和執行語言表示式的設計模式。它可以靈活地對語言進行解釋和執行,適用於處理簡單的、數量有限的語言表示式。

案例場景:

指令:
方向:up=向上,down=向下,left=向左,right=向右
模式:move=移動,run=快速移動
距離:實際值,不解釋

表示式:string expression="up move 100 and down run 200 and left run 300";
指令格式:方向 運動模式 距離值

Abstract Expression

public abstract class ExpressionBase
    {
        public abstract string Interpret();
    }

Terminal Expression

/// <summary>
    /// 方向模式的直譯器表示式
    /// </summary>
    public class DirectionExpression : ExpressionBase
    {
        private string content;

        public DirectionExpression(string content)
        {
            this.content = content;
        }

        public override string Interpret()
        {
            switch (content)
            {
                case "up":
                    return "向上";
                    break;
                case "down":
                    return "向下";
                    break;
                case "left":
                    return "向左";
                    break;
                case "right":
                    return "向右";
                    break;
                default:
                    return "方向錯誤";
                    break;
            }
        }
    }
/// <summary>
    /// 運動模式的直譯器表示式
    /// </summary>
    public class ModeExpression : ExpressionBase
    {
        private string content;

        public ModeExpression(string content)
        {
            this.content = content;
        }
        public override string Interpret()
        {
             if(this.content=="move")
            {
                return "移動";
            }
             else if(content=="run")
            {
                return "快速移動";
            }
             else
            {
                return "模式錯誤";
            }
        }
    }
/// <summary>
    /// 距離表示式
    /// </summary>
    public class DistanceExpression : ExpressionBase
    {
        private string content;

        public DistanceExpression(string content)
        {
            this.content = content;
        }
        public override string Interpret()
        {
            return content;
        }
    }

/// <summary>
    /// 終結符表示式
    /// </summary>
    public class TerminalExpression: ExpressionBase
    {
        private ExpressionBase direction, mode, distance;

        public TerminalExpression(ExpressionBase direction, ExpressionBase mode, ExpressionBase distance)
        {
            this.direction = direction;
            this.mode = mode;
            this.distance = distance;
        }

        public override string Interpret()
        {
            return string.Concat(direction.Interpret(), mode.Interpret(), distance.Interpret());
        }
    }

Non-terminal Expression

/// <summary>
    /// 非終結符表示式
    /// </summary>
    public class NonTerminalExpression : ExpressionBase
    {
        private ExpressionBase left,right;

        public NonTerminalExpression(ExpressionBase left, ExpressionBase right)
        {
            this.left = left;
            this.right = right;
        }   

        public override string Interpret()
        {
            return $"{left.Interpret()}  然後  {right.Interpret()}";
        }
    }

Context

public class Context
    {
        private Stack<ExpressionBase> stack=new Stack<ExpressionBase>();
        private ExpressionBase direction, mode, distance, all;
        public void Execute(string content)
        {
            string[] array = content.Split(' ');
            for(int i=0;i<array.Length;i++)
            {
                if (array[i]=="and")
                {
                    ExpressionBase left=stack.Pop();
                    direction = new DirectionExpression(array[++i]);
                    mode = new ModeExpression(array[++i]);
                    distance = new DistanceExpression(array[++i]);
                    ExpressionBase right=new TerminalExpression(direction, mode, distance);
                    ExpressionBase end = new NonTerminalExpression(left, right);
                    stack.Push(end);
                }
                else
                {
                    direction= new DirectionExpression(array[i]);
                    mode = new ModeExpression(array[++i]);
                    distance = new DistanceExpression(array[++i]);
                    ExpressionBase end =new TerminalExpression(direction, mode, distance);
                    stack.Push(end);
                }
            }
            all=stack.Pop();
        }

        public string InterpretAll()
        {
            return all.Interpret();
        }
    }

呼叫

 internal class Client
    {
        public void Start()
        {
            Context context = new Context();
            string expression = "up move 100 and down run 200 and left run 300";
            context.Execute(expression);
            string result = context.InterpretAll();
            Console.WriteLine(result);
        }
    }
 static void Main(string[] args)
        {
            new Client().Start();
            Console.ReadKey();
            Console.WriteLine("Hello, World!");
        }

相關文章