using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3.行为型模式_解释器模式
{
#region
//定义:定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。
//角色:
//AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。
//TerminalExpression(终结符表达式):终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,
//在句子中的每一个终结符都是该类的一个实例。
//通常在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。
// NonterminalExpression(非终结符表达式):非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,
//由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
//Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。
//适用场景:
//(1) 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
//(2) 一些重复出现的问题可以用一种简单的语言来进行表达。
//(3) 一个语言的文法较为简单,且执行效率不是关键的问题。
//1. 当需要一个命令解释权来解析用户的命令的时候。
//2. 当程序需要解析代数符号串的时候,比如需要计算一个数学表达式的值。
//3. 当程序需要产生各种不同的输出的时候。就比如不同的SQL语句对应完全不用的用户数据输出
//优点:
//(1) 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
//(2) 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
//(3) 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,
//这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
//(4) 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,
//原有表达式类代码无须修改,符合“开闭原则”。
//缺点:
//(1) 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,
//导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
//(2) 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
#endregion
class Program
{
//抽象表达式 父类
public abstract class AbstractNode
{
public abstract string Interpret();
}
#region 非终结符表达式
//And解释
public class AndNode : AbstractNode
{
private AbstractNode left; //And的左表达式
private AbstractNode right; //And的右表达式
public AndNode(AbstractNode left, AbstractNode right)
{
this.left = left;
this.right = right;
}
//And表达式解释操作
public override string Interpret()
{
return left.Interpret() + ", 再" + right.Interpret();
}
}
//简单句子解释
public class SentenceNode : AbstractNode
{
private AbstractNode direction;
private AbstractNode action;
private AbstractNode distance;
public SentenceNode(AbstractNode direction, AbstractNode action, AbstractNode distance)
{
this.direction = direction;
this.action = action;
this.distance = distance;
}
//简单句子的解释操作
public override string Interpret()
{
return direction.Interpret() + action.Interpret() + distance.Interpret();
}
}
#endregion
#region 终结符表达式
//方向解释
public class DirectionNode : AbstractNode
{
private string direction;
public DirectionNode(string direction)
{
this.direction = direction;
}
//方向表达式的解释操作
public override string Interpret()
{
if (direction.Equals("up", StringComparison.CurrentCultureIgnoreCase))
{
return "向上";
}
else if (direction.Equals("down", StringComparison.CurrentCultureIgnoreCase))
{
return "向下";
}
else if (direction.Equals("left", StringComparison.CurrentCultureIgnoreCase))
{
return "向左";
}
else if (direction.Equals("right", StringComparison.CurrentCultureIgnoreCase))
{
return "向右";
}
else
{
return "无效指令";
}
}
}
//动作解释
public class ActionNode : AbstractNode
{
private string action;
public ActionNode(string action)
{
this.action = action;
}
//动作(移动方式)表达式的解释操作
public override string Interpret()
{
if (action.Equals("move", StringComparison.CurrentCultureIgnoreCase))
{
return "移动";
}
else if (action.Equals("run", StringComparison.CurrentCultureIgnoreCase))
{
return "快速移动";
}
else
{
return "无效指令";
}
}
}
//距离解释
public class DistanceNode : AbstractNode
{
private string distance;
public DistanceNode(string distance)
{
this.distance = distance;
}
//距离表达式的解释操作
public override string Interpret()
{
return this.distance;
}
}
#endregion
#region 环境工具类
//指令处理类、、存储并翻译需要解释的语句
public class InstructionHandler
{
private AbstractNode node;
public void Handle(string instruction)
{
AbstractNode left = null, right = null;
AbstractNode direction = null, action = null, distance = null;
Stack stack = new Stack(); //声明一个栈对象用于存储抽象语法树
string[] words = instruction.Split(' '); //以空格分隔指令字符串
for (int i = 0; i < words.Length; i++)
{
// 本实例采用栈的方式来处理指令,如果遇到“and”,
// 则将其后的三个单词作为三个终结符表达式连成一个简单句子SentenceNode,
// 作为“and”的右表达式,而将从栈顶弹出的表达式作为“and”的左表达式,
// 最后将新的“and”表达式压入栈中。
if (words[i].Equals("and", StringComparison.CurrentCultureIgnoreCase))
{
left = (AbstractNode)stack.Pop(); //弹出栈顶表达式作为左表达式
string word1 = words[++i];
direction = new DirectionNode(word1);
string word2 = words[++i];
action = new ActionNode(word2);
string word3 = words[++i];
distance = new DistanceNode(word3);
right = new SentenceNode(direction, action, distance); //右表达式
stack.Push(new AndNode(left, right)); //将新表达式压入栈中
}
//如果是从头开始进行解释,则将前三个单词组成一个简单句子SentenceNode并将该句子压入栈中
else
{
string word1 = words[i];
direction = new DirectionNode(word1);
string word2 = words[++i];
action = new ActionNode(word2);
string word3 = words[++i];
distance = new DistanceNode(word3);
left = new SentenceNode(direction, action, distance);
stack.Push(left); //将新表达式压入栈中
}
}
this.node = (AbstractNode)stack.Pop(); //将全部表达式从栈中弹出
}
public string Output()
{
string result = node.Interpret(); //解释表达式
return result;
}
}
#endregion
static void Main(string[] args)
{
string instruction = "up move 5 and down run 10 and left move 5";
InstructionHandler handler = new InstructionHandler();
handler.Handle(instruction);
string outString;
outString = handler.Output();
Console.WriteLine(outString);
Console.ReadLine();
}
}
}
c#设计模式15——行为型模式_解释器模式
最新推荐文章于 2024-08-05 22:47:24 发布