用Unity写设计模式-解释器模式

解释器模式

    • 解释器模式介绍
    • 解释器模式
    • 解释器模式案例1
    • 解释器模式案例2

解释器模式介绍

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

  • AbstractExpression(表达)

声明执行操作的接口

  • TerminalExpression 表达式(ThousandExpression, HundredExpression, TenExpression, OneExpression)

实现与语法中的终止符号相关联的“解释”操作。
句子中的每个终端符号都需要一个实例。

  • NonterminalExpression(未使用)

每个规则R::= R1R2… 语法中的Rn
维护从R1到Rn的每个符号的AbstractExpression类型的实例变量。
为语法中的非终结符实现一个“解释”操作。 Interpret通常在表示R1到Rn的变量上递归地调用自己。

  • Context(上下文)

包含解释器的全局信息

  • Client 客户机(InterpreterApp)

构建(或给出)一个抽象语法树,表示该语法定义的语言中的特定句子。
抽象语法树是由NonterminalExpression和TerminalExpression类的实例组装而成的,调用Interpret操作

解释器模式

using UnityEngine;
using System.Collections;

public class InterpreterStructrue : MonoBehaviour
{
     
	void Start ( )
    {
     
        Context context = new Context();

        // Usually a tree 
        ArrayList list = new ArrayList();

        // Populate 'abstract syntax tree' 
        list.Add(new TerminalExpression());
        list.Add(new NonterminalExpression());
        list.Add(new TerminalExpression());
        list.Add(new TerminalExpression());

        // Interpret
        foreach (AbstractExpression exp in list)
        {
     
            exp.Interpret(context);
        }

    }
}

/// 
/// The 'Context' class
/// 
class Context
{
     
}

/// 
/// The 'AbstractExpression' abstract class
/// 
abstract class AbstractExpression
{
     
    public abstract void Interpret(Context context);
}

/// 
/// The 'TerminalExpression' class
/// 
class TerminalExpression : AbstractExpression
{
     
    public override void Interpret(Context context)
    {
     
        Debug.Log("Called Terminal.Interpret()");
    }
}

/// 
/// The 'NonterminalExpression' class
/// 
class NonterminalExpression : AbstractExpression
{
     
    public override void Interpret(Context context)
    {
     
        Debug.Log("Called Nonterminal.Interpret()");
    }
}

解释器模式案例1

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//这段代码演示了解释器模式,该模式用于将罗马数字转换为十进制。  
namespace InterpreterExample1
{
     
    public class InterpreterExample1 : MonoBehaviour
    {
     
        void Start()
        {
     
            string roman = "MCMXXVIII";
            Context context = new Context(roman);

            // Build the 'parse tree'
            List<Expression> tree = new List<Expression>();
            tree.Add(new ThousandExpression());
            tree.Add(new HundredExpression());
            tree.Add(new TenExpression());
            tree.Add(new OneExpression());

            // Interpret
            foreach (Expression exp in tree)
            {
     
                exp.Interpret(context);
            }

            Debug.Log(roman+" = "+ context.Output);
        }
    }

    /// 
    /// The 'Context' class
    /// 
    class Context
    {
     
        private string _input;
        private int _output;

        // Constructor
        public Context(string input)
        {
     
            this._input = input;
        }

        // Gets or sets input
        public string Input
        {
     
            get {
      return _input; }
            set {
      _input = value; }
        }

        // Gets or sets output
        public int Output
        {
     
            get {
      return _output; }
            set {
      _output = value; }
        }
    }

    /// 
    /// The 'AbstractExpression' class
    /// 
    abstract class Expression
    {
     
        public void Interpret(Context context)
        {
     
            if (context.Input.Length == 0)
                return;

            if (context.Input.StartsWith(Nine()))
            {
     
                context.Output += (9 * Multiplier());
                context.Input = context.Input.Substring(2);
            }
            else if (context.Input.StartsWith(Four()))
            {
     
                context.Output += (4 * Multiplier());
                context.Input = context.Input.Substring(2);
            }
            else if (context.Input.StartsWith(Five()))
            {
     
                context.Output += (5 * Multiplier());
                context.Input = context.Input.Substring(1);
            }

            while (context.Input.StartsWith(One()))
            {
     
                context.Output += (1 * Multiplier());
                context.Input = context.Input.Substring(1);
            }
        }

        public abstract string One();
        public abstract string Four();
        public abstract string Five();
        public abstract string Nine();
        public abstract int Multiplier();
    }

    /// 
    /// A 'TerminalExpression' class
    /// 
    /// Thousand checks for the Roman Numeral M 
    /// 
    /// 
    class ThousandExpression : Expression
    {
     
        public override string One() {
      return "M"; }
        public override string Four() {
      return " "; }
        public override string Five() {
      return " "; }
        public override string Nine() {
      return " "; }
        public override int Multiplier() {
      return 1000; }
    }

    /// 
    /// A 'TerminalExpression' class
    /// 
    /// Hundred checks C, CD, D or CM
    /// 
    /// 
    class HundredExpression : Expression
    {
     
        public override string One() {
      return "C"; }
        public override string Four() {
      return "CD"; }
        public override string Five() {
      return "D"; }
        public override string Nine() {
      return "CM"; }
        public override int Multiplier() {
      return 100; }
    }

    /// 
    /// A 'TerminalExpression' class
    /// 
    /// Ten checks for X, XL, L and XC
    /// 
    /// 
    class TenExpression : Expression
    {
     
        public override string One() {
      return "X"; }
        public override string Four() {
      return "XL"; }
        public override string Five() {
      return "L"; }
        public override string Nine() {
      return "XC"; }
        public override int Multiplier() {
      return 10; }
    }

    /// 
    /// A 'TerminalExpression' class
    /// 
    /// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
    /// 
    /// 
    class OneExpression : Expression
    {
     
        public override string One() {
      return "I"; }
        public override string Four() {
      return "IV"; }
        public override string Five() {
      return "V"; }
        public override string Nine() {
      return "IX"; }
        public override int Multiplier() {
      return 1; }
    }
}

解释器模式案例2

using System;
using UnityEngine;
using System.Collections;
using System.Globalization;
using System.Reflection;

public class InterpreterExample2 : MonoBehaviour
{
     
	void Start ( )
	{
     
        string question1 = "2 Gallons to pints";
        AskQuestion(question1);

        string question2 = "4 Gallons to tablespoons";
        AskQuestion(question2);
    }

    protected void AskQuestion(string question)
    {
     
        ConversionContext context = new ConversionContext(question);

        string fromConversion = context.fromConversion; // in this example fromConversion is always the second word
        string toConversion = context.toConversion;
        double quantity = context.quantity;

        // Trying to get a matching class for the word "fromConversion"
        try
        {
     
            // Getting the type, we also have to define the namespace (in this case InterpreterPattern as defined above)
            // and fromConversion should hold the class name (in this case Gallons)
            Type type = Type.GetType("InterpreterPattern." + fromConversion);
            object instance = Activator.CreateInstance(type);
            Expression expression = instance as Expression;

            // Get the matching method: e.g. (toConversion = pints)
            MethodInfo method = type.GetMethod(toConversion);
            string result = (string)method.Invoke(instance, new object[] {
      quantity });

            Debug.Log("Output: " + quantity.ToString() + "  " + fromConversion + " are " + result + " " + toConversion);
        }
        catch (Exception e)
        {
     
            Debug.Log(e.Message);
        }
    }
}


// Context object that does try to make sense of an input string:
public class ConversionContext
{
     
    public string conversionQues {
      get; protected set; }

    public string fromConversion {
      get; protected set; }

    public string toConversion {
      get; protected set; }

    public double quantity {
      get; protected set; }

    protected string[] partsOfQues;



    // here happens the sensemaking
    public ConversionContext(string input)
    {
     
        Debug.Log("Input: " + input);
        this.conversionQues = input;
        this.partsOfQues = input.Split(new string[] {
      " " }, System.StringSplitOptions.RemoveEmptyEntries);

        if (partsOfQues.Length >= 4)
        {
     

            fromConversion = GetCapitalized(partsOfQues[1]);
            // 1 gallon to pints
            toConversion = GetLowerCase(partsOfQues[3]);

            // get quantitiy:
            double quant;
            double.TryParse(partsOfQues[0], out quant);
            this.quantity = quant;
        }
    }

    // Some helper methods:
    protected string GetCapitalized(string word)
    {
     
        word = word.ToLower();
        word = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(word);

        // make sure a 's' is appended
        if (word.EndsWith("s") == false)
        {
     
            word += "s";
        }

        return word;
    }

    protected string GetLowerCase(string word)
    {
     
        return word.ToLower();
    }
}




// Definition of all the things the concrete expression
// shall be able to convert into
public abstract class Expression
{
     
    public abstract string gallons(double quantity);

    public abstract string quarts(double quantity);

    public abstract string pints(double quantity);

    public abstract string cups(double quantity);

    public abstract string tablespoons(double quantity);
}


// concrete class
public class Gallons : Expression
{
     
    #region implemented abstract members of Expression

    public override string gallons(double quantity)
    {
     
        return quantity.ToString();
    }

    public override string quarts(double quantity)
    {
     
        return (quantity * 4).ToString();
    }

    public override string pints(double quantity)
    {
     
        return (quantity * 8).ToString();
    }

    public override string cups(double quantity)
    {
     
        return (quantity * 16).ToString();
    }

    public override string tablespoons(double quantity)
    {
     
        return (quantity * 256).ToString();
    }

    #endregion
}

你可能感兴趣的:(每天一个设计模式)