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

这篇博客介绍了解释器模式,通过示例展示了如何用该模式将罗马数字转换为十进制数。首先解释了解释器模式的基本概念,然后提供了一个具体的案例,创建了抽象语法树并遍历解释每个节点,最终将输入的罗马数字字符串转换成相应的十进制数值。
摘要由CSDN通过智能技术生成

解释器模式介绍

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

  • 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);
        }

    }
}

/// <summary>
/// The 'Context' class
/// </summary>
class Context
{
}

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

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

/// <summary>
/// The 'NonterminalExpression' class
/// </summary>
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);
        }
    }

    /// <summary>
    /// The 'Context' class
    /// </summary>
    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; }
        }
    }

    /// <summary>
    /// The 'AbstractExpression' class
    /// </summary>
    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();
    }

    /// <summary>
    /// A 'TerminalExpression' class
    /// <remarks>
    /// Thousand checks for the Roman Numeral M 
    /// </remarks>
    /// </summary>
    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; }
    }

    /// <summary>
    /// A 'TerminalExpression' class
    /// <remarks>
    /// Hundred checks C, CD, D or CM
    /// </remarks>
    /// </summary>
    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; }
    }

    /// <summary>
    /// A 'TerminalExpression' class
    /// <remarks>
    /// Ten checks for X, XL, L and XC
    /// </remarks>
    /// </summary>
    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; }
    }

    /// <summary>
    /// A 'TerminalExpression' class
    /// <remarks>
    /// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
    /// </remarks>
    /// </summary>
    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
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值