熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

老生常談:解釋器模式

2013-11-13 10:21:10  來源: .NET編程 
     解釋器模式的目的:

  如果某一類問題一再的發生此時比較好的做法是將此類問題的各個實例表達為一個簡單語言中的語句這樣可以建造一個解釋器通過解釋這些語句達到解決問題的目的

  解釋器模式的定義

  定義語言的文法並且建立一個解釋器來解釋該語言中的句子它屬於類的行為模式這裡的語言意思是使用規定格式和語法的代碼

  示意案例:

  解釋器這個模式在實際應用當中應用並不廣泛能想到的例子也不多可能是我水平不夠這裡我拿一個把大寫數字輸出為阿拉伯數字數字的需求來用解釋器模式實現例如

  :伍千肆百參拾貳輸出為

  :當用戶輸入的是數字字符串時直接輸入數字例如直接輸出

  解釋器模式的結構

   

  模式所涉及的角色

  :抽象表達式角色聲明一個所有的具體表達式角色都需要實現的抽象接口這個接口主要是一個interprect方法我們叫解釋方法

  注意本示例中的抽象表達式角色中的解釋方法並非抽象方法因為這個案例特殊數字解釋的方法過程一樣


/// <summary>
    /// 抽象表達式角色
    /// </summary>
    public abstract class Expression
    {
        /// <summary>
        /// 漢字數字與阿拉伯數字數字的對應字典
        /// </summary>
        protected Dictionary<string int> table = new Dictionary<string int>();
        public Expression()
        {
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
            tableAdd( );
        }
        /// <summary>
        /// 所有的具體表達式角色都需要實現的抽象方法
        /// 這個方法為虛方法並非抽象方法為了代碼復用
        /// </summary>
        /// <param name=context>環境角色</param>
        public virtual void  Interpret(Context context)
        {
            //如果要處理的字符串長度為則返回
            if (contextstatementLength == )
            {
                return ;
            }
            foreach (string key in tableKeys)
            {
                int value = table[key];
                if (contextstatementEndsWith(key + GetPostifix()))
                {
                    contextdata += value * Multiplier();
                    contextstatement = contextstatementSubstring( contextstatementLength  thisGetLength());
                    break;
                }

                if (contextstatementEndsWith())
                {
                    contextstatement = contextstatementSubstring( contextstatementLength  );
                    break;
                }
                if (contextstatementLength == )
                {
                    return ;
                }
            }       
        }
        /// <summary>
        /// 取漢字數字單位
        /// 個位數為空
        /// 十位數為十
        /// 百位數為百
        /// 千位數為千
        /// </summary>
        /// <returns></returns>
        public abstract string GetPostifix();
        /// <summary>
        /// 例如:個位上數字為則最後為*
        /// 例如:百位上數字為則表示*
        /// </summary>
        /// <returns></returns>
        public abstract int Multiplier();
        /// <summary>
        /// 例如:個位的長度為一位
        /// 例如數字三十表示兩位
        /// 例如四百表示兩位
        /// </summary>
        /// <returns></returns>
        public virtual int GetLength()
        {
            return thisGetPostifix()Length + ;
        }
    }

  終結符表達式角色一個具體角色

  >實現了抽象表達式角色所要求的接口主要是interpret方法

  >:方法中的每一個終結符都有一個具體終結表達式與之相對應

  說明如果用戶輸入的內容不是漢字而是數字字符串則直接輸出不必解釋


/// <summary>
    /// 終結符表達式角色
    /// 如果能換算成數字則直接換算後返回
    /// </summary>
    class TerminalExpression : Expression
    {
        /// <summary>
        /// 重寫解釋方法
        /// </summary>
        /// <param name=context>環境角色</param>
        public override void Interpret(Context context)
        {
            int i = ;
            try
            {
                i = intParse(contextstatement);
                //如果是數字則說明能夠直接轉換
                //也就是說用不到非終結表達式角色
                contextstatement = ;
                contextdata = i;
            }
            catch
            {
                //說明輸入的是漢字數字不做任何處理
            }           
        }
        public override string GetPostifix()
        {
            return ;
        }
        public override int Multiplier() { return ; }
    }

  非終結符表達式角色這也是一個具體角色

  >:文法中的每一條規則R=RRRn都需要一個具體的非終結符表達式類;

  >:對每一個RR中的符號都持有一個靜態類型為Expression的實例變量;                

  >:實現解釋操作解釋操作以遞歸的方式調用上面所提到的代表RR中的各個符號的實例變量

  注意本示例中由於解釋的方法都一樣為些非終結符表達中的解釋方法在沒有重寫的情況下調用抽象表達式角色的解釋方法


   /// <summary>
    /// 非終結表達式角色
    /// 解釋個位數
    /// </summary>
    public class NonterminalOneExpression : Expression
    {
        public override string GetPostifix()
        {
            return ;
        }
        public override int Multiplier() { return ; }
        public override int GetLength()
        {
            return ;
        }
    }
/// <summary>
    /// 非終結表達式角色
    /// 解釋十位數
    /// </summary>
    public class NonterminalTenExpression : Expression
    {
        public override string GetPostifix()
        {
            return ;
        }
        public override int Multiplier() { return ; }
        public override int GetLength()
        {
            return ;
        }
    }
    /// <summary>
    /// 非終結表達式角色
    /// 解釋百位數
    /// </summary>
    public class NonterminalHundredExpression : Expression
    {
        public override string GetPostifix()
        {
            return ;
        }
        public override int Multiplier() { return ; }
        public override int GetLength()
        {
            return ;
        }
    }
    /// <summary>
    /// 非終結表達式角色
    /// 解釋千位數
    /// </summary>
    public class NonterminalThousandExpression : Expression
    {
        public override string GetPostifix()
        {
            return ;
        }
        public override int Multiplier() { return ; }
        public override int GetLength()
        {
            return ;
        }
    }

  客戶端角色

  >:建造一個抽象語法樹;抽象語法樹的每一個節點都代表一個語句而在每一個節點上都可以執行解釋方法這個方法的執行就代表這個語句的解釋

  >:調用解釋操作


string roman = 伍千肆百參拾貳; //
            Context context = new Context(roman);
            //構造抽象語法樹
            ArrayList tree = new ArrayList();
            //加入終結符表達式
            //如果能直接轉換成數字則直接返回
            treeAdd(new TerminalExpression());
            //非終結符處理個位數
            treeAdd(new NonterminalOneExpression());
            //非終結符處理十位數
            treeAdd(new NonterminalTenExpression());
            //非終結符處理百位數
            treeAdd(new NonterminalHundredExpression());
            //非終結器處理千位數
            treeAdd(new NonterminalThousandExpression());
            //對抽象語法樹的每個枝節進行解釋操作
            foreach (Expression exp in tree)
            {
                expInterpret(context);
            }
            ConsoleWriteLine({} = {} roman contextdata);

   環境角色提供解釋器之外的一些全局信息比如變量的真實量值


 /// <summary>
    /// 環境角色
    /// </summary>
    public class Context
    {
        /// <summary>
        /// 漢字表示的數字
        /// </summary>
        public string statement
        {
            get;
            set;
        }
        /// <summary>
        /// 阿拉伯數字
        /// </summary>
        public int data
        {
            get;
            set;
        }
        /// <summary>
        /// 構造函數
        /// 接受一個漢字表達式數字
        /// </summary>
        /// <param name=statement>漢字表達式數字</param>
        public Context(string statement)
        {
            thisstatement = statement;
        }
    }

  解釋器模式適用性

            系統有一個簡單的語言可供解釋

  一些重復發生的問題可以用這種簡單的語言表達

  效率不是主要的考慮


From:http://tw.wingwit.com/Article/program/net/201311/13348.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.