유 니 티 로 디자인 모드. - 해석 기 모드.
63786 단어 매일 하나의 디자인 모델
해석 기 모드 소개
언어 를 지정 하고 문법 을 정의 하 는 표현 을 정의 하 며 해석 기 를 정의 합 니 다. 이 해석 기 는 이 표현 을 사용 하여 언어 중의 문장 을 설명 합 니 다.
해석 기 모드
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
}