面向對象設計模式之Interpreter解釋器模式(行爲型)

 動機:在軟件構建過程當中 ,若是某一特定領域的問題比較複雜,相似的模式不斷重複出現,若是使用普通的編程方式來實現將面臨很是頻繁的變化。在這種狀況下,將特定領域的問題表達爲某種語法規則的句子,而後構建一個解釋器來解釋這樣的句子,從而達到解決問題的目的。
意圖:給定一個語言,定義它的文法的一種表示,並定義一種解釋器,這個解釋器使用該表示來解釋語言中的句子。express

UML圖解:編程

示例:接收中文形式的數字表示並能以羅馬形式數字輸出,應用解釋器模式設計,如:四百七十一萬六千四百五十二 =》4716452。代碼以下ide

namespace Interpreter
{
    /// <summary>
    /// 定義一個數據上下文
    /// </summary>
    public class Context
    {
        string statement="";//待解釋的數據
        int data;//解釋以後的數據
        public Context (string statement)
        {
            this.statement = statement;
        }
        public int Data
        {
            get { return data; }
            set { data = value; }
        }
        public string Statement
        {
            get { return statement; }
            set { statement = value; }
        }


    }

    /// <summary>
    /// 抽象表達式解釋器
    /// </summary>
    public abstract class Expression
    {
        protected Dictionary<string, int> table = new Dictionary<string, int>(9);
        public 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);
        }

        /// <summary>
        /// 解釋給定的中文表示數字上下文對象
        /// </summary>
        /// <param name="context"></param>
        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 - GetLength());
                }
                if (context.Statement.EndsWith("零"))//應對如"四百七十一萬零六千四百零五十二"中出現'零'的狀況
                {
                    context.Statement=context.Statement.Substring(0,context.Statement.Length-1);
                }
            }
        }

        /// <summary>
        /// 獲取如「六千四百五十二」中,獲取千位的'千'字,百位的'百'字,十位的'十'字
        /// </summary>
        /// <returns></returns>
        public abstract string GetPostfix();

        /// <summary>
        /// 陪增級數(個-1,十位-10,百位-100,千位-1000)
        /// </summary>
        /// <returns></returns>
        public abstract int Multiplier();

        /// <summary>
        /// 獲取符合文法的一組長度(如獲取「四百」,「五十」的長度)
        /// </summary>
        /// <returns></returns>
        public virtual int GetLength()
        {
            return this.GetPostfix().Length + 1;
        }
    }
    
    /// <summary>
    /// 個位解釋器 解析個位
    /// </summary>
    public class GeExpression : Expression
    {

        public override string GetPostfix()
        {
            return "";
        }

        public override int Multiplier()
        {
            return 1;
        }


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

    /// <summary>
    /// 十位解釋器 解析個位+十位
    /// </summary>
    public class ShiExpression : Expression
    {

        public override string GetPostfix()
        {
            return "十";
        }

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

    /// <summary>
    /// 百位解釋器 解析個位+十位+百位
    /// </summary>
    public class BaiExpresssion : Expression
    {

        public override string GetPostfix()
        {
            return "百";
        }

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

    /// <summary>
    /// 千位解釋器 解析個位+十位+百位+千位
    /// </summary>
    public class QianExpression : Expression
    {

        public override string GetPostfix()
        {
            return "千";
        }

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

    /// <summary>
    /// 萬位解釋器 解析個位+十位+百位+千位+萬位
    /// </summary>
    public class WanExpression : Expression
    {
        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 BaiExpresssion());
            tree.Add(new QianExpression());

            foreach (string key in table.Keys)
            {
                if (context.Statement.EndsWith(this.GetPostfix()))
                {
                    int temp = context.Data;
                    context.Data = 0;
                    context.Statement=context.Statement.Substring(0, context.Statement.Length - 1);
                    foreach(Expression expression in tree)
                    {
                        expression.Interpreter(context);
                    }
                    context.Data = temp+this.Multiplier()*context.Data;
                }
            }
           
            
        }

        public override string GetPostfix()
        {
            return "萬";
        }

        public override int Multiplier()
        {
            return 10000;
        }
    }
    //經過Interpreter模式很容易擴展億相對的YiExpression類

    public class App
    {
        public static void Main()
        {

            string chinese="四百七十一萬六千四百五十二";
            Context context =new Context(chinese);
            ArrayList tree = new ArrayList();//需按順序添加個十百千萬等解釋表達式對象
            tree.Add(new GeExpression());
            tree.Add(new ShiExpression());
            tree.Add(new BaiExpresssion());
            tree.Add(new QianExpression());
            tree.Add(new WanExpression());
            foreach (Expression exp in tree)
            {
                exp.Interpreter(context);
            }
            Console.WriteLine("{0}={1}",chinese,context.Data);
        }
    }
}

 Interpreter模式的幾個要點:工具

1.Interpreter模式的應用場景時Interpreter模式應用中的難點,只有知足「業務規則頻繁變化,且 相似的模式不斷重複出現,而且容易抽象爲語法規則的問題」才合適使用Interpreter模式。this

2.使用Interpreter模式來表示文法規則,從而能夠使用面向對象技巧來方便地「擴展」文法。spa

3.Interpreter模式比較適合簡單的文法表示,對於複雜的文法表示,Interpreter模式會產生比較大的類 層次結構,須要求助於語法分析生成器這樣的標準工具。設計

相關文章
相關標籤/搜索