2013年8月1日 星期四

設計模式:解釋器模式 (Interpreter Pattern)

解釋器模式 (Interpreter Pattern),以下程式碼以 C# 為例

說明:
用來解釋、直譯一種語言的方法。

範例:
年份可以對應到12生肖、12地支,
假設我自訂「a2013」表示是2013年的生肖,「b2013」表示是2013年的地支,
開頭的「a」表示生肖、「b」表示地支,後面的「2013」表示年份。

希望達成如下的效果
static void Main(string[] args)
{
    // 待解譯文字
    Context context = new Context();
    context.Text = "b2002 a2002 b2013 a2013";

    // 解譯器
    Expression expression = null;

    while (context.Text.Length > 0)
    {
        switch (context.Text.Substring(0, 1))
        {
            case "a":
                expression = new ExpressionA(); // 生肖
                break;
            case "b":
                expression = new ExpressionB(); // 地支
                break;
        }

        expression.Interpret(context);
    }

    Console.Read();
}
執行結果:
午馬巳蛇

實現重點在於,將待解釋的字串交給合適的解譯器處理。

其餘程式碼
// 解譯器抽像類別
abstract class Expression
{
    public void Interpret(Context context)
    {
        if (context.Text.Length > 0)
        {
            // 取得前面第一個分隔字串
            int spacePos = context.Text.IndexOf(" ");
            string word = "";
            if (-1 != spacePos)
            {
                word = context.Text.Substring(0, spacePos);
                // 將剩下的字串重新設定到未解譯的資料
                context.Text = context.Text.Substring(spacePos + 1);

            }
            else
            {
                // 最後一個字串
                word = context.Text;
                context.Text = "";
            }

            // 單字解譯
            int num = (Convert.ToInt32(word.Substring(1)) + 9) % 12;
            if (0 == num)
            {
                num = 12;
            }
            Excute(num);
        }
    }

    public abstract void Excute(int num);
}

// 生肖解譯器
class ExpressionA : Expression
{
    public override void Excute(int num)
    {
        string res = "";
        switch (num)
        {
            case 1:
                res = "鼠";
                break;
            case 2:
                res = "牛";
                break;
            case 3:
                res = "虎";
                break;
            case 4:
                res = "兔";
                break;
            case 5:
                res = "龍";
                break;
            case 6:
                res = "蛇";
                break;
            case 7:
                res = "馬";
                break;
            case 8:
                res = "羊";
                break;
            case 9:
                res = "猴";
                break;
            case 10:
                res = "雞";
                break;
            case 11:
                res = "狗";
                break;
            case 12:
                res = "豬";
                break;
        }

        Console.Write(res);
    }
}

// 地支解譯器
class ExpressionB : Expression
{
    public override void Excute(int num)
    {
        string res = "";
        switch (num)
        {
            case 1:
                res = "子";
                break;
            case 2:
                res = "丑";
                break;
            case 3:
                res = "寅";
                break;
            case 4:
                res = "卯";
                break;
            case 5:
                res = "辰";
                break;
            case 6:
                res = "巳";
                break;
            case 7:
                res = "午";
                break;
            case 8:
                res = "未";
                break;
            case 9:
                res = "申";
                break;
            case 10:
                res = "酉";
                break;
            case 11:
                res = "戌";
                break;
            case 12:
                res = "亥";
                break;
        }

        Console.Write(res);
    }
}

// 存放待解譯資料
class Context
{
    private string text;
    public string Text
    {
        get { return text; }
        set { text = value; }
    }
}

相關連結:設計模式整理列表

3 則留言:

  1. 你好,
    谢谢你的总结!
    我正在阅读并尝试运行范例,但是可能是缺少lib,我的范例中context.Text 是无法识别。
    请问能不能给我提示。

    谢谢!

    回覆刪除
    回覆
    1. 你好,不好意思,是我遺漏了 Context 類別,已補在程式碼最後面,你再試看看。

      刪除
  2. 加入Context 类别后,代码可以运行,谢谢!

    回覆刪除