一、定义
①、什么是解释器模式
给定一个语言,定义它得到文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
②、主要解决什么问题
对于一些固定的文法构建一个解释句子的解释器
③、如何解决
构建语法树,定义终极符与非终结符
④、什么时候使用
如果一种特定类型的问题发生的频率足够高,那么可能就值得该问题的各个实例表述为一个简单语言的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题
⑤、使用场景
- 可以将一个需要解释执行的语言中的句子表示为一个抽象的语法树
- 一些重复出现的问题可以用一种简单的语言来进行表达
- 一个简单语法需要解释的场景
⑥、优缺点
优点
- 可扩展性比较好,灵活。
- 增加了新的解释表达式的方法
- 易于实现简单文法
缺点 - 可利用场景比较少
- 对于复杂的文法比较难以维护
- 解释器模式会引起类膨胀
- 解释器模式采用递归调用方法
二、图
概念图
拓展图
示例图:上海滩演奏
三、代码
①、代码类图
客户端
static void Main(string[] args)
{
PlayContext context = new PlayContext();//实例化一个演奏内容
//音乐-上海滩
Console.WriteLine("上海滩:"); //控制台上显示内容
context.PlayText ="O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 "; //设置文本内容
Expression expression = null;
try
{
while (context.PlayText.Length>0) //演奏内容是否大于零
{
string str = context.PlayText.Substring(0, 1);//str=截取索引为0的字符串
switch (str ) //判断str内容
{
case "O": //str=O
expression = new Scale(); //实例化音阶类
break;
case "C":
case "D":
case "E":
case "F":
case "G":
case "A":
case "B":
case "P":
expression = new Note(); //实例化音符类
break;
}
expression.Interpret(context); //执行解释器interpret方法
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); //显示错误信息
}
Console.Read();
}
演奏内容类
//演奏内容
class PlayContext
{
//演奏文本
private string text;
public string PlayText
{
get { return text; }
set { text = value; }
}
}
表达式类
//表达式类
abstract class Expression
{
//解释器
public void Interpret(PlayContext context)
{
if (context.PlayText.Length == 0) //判断文本长度时候为零
{
return; //返回
}
else
{
string playKey = context.PlayText.Substring(0, 1); //对playKey进行赋值,截取索引为0-1之前字符串
context.PlayText = context.PlayText.Substring(2); //去除前两个字符串
double playValue = Convert.ToDouble(context.PlayText.Substring(0, context.PlayText.IndexOf(" "))); //对playText进行赋值,截取0到第一个空格之前
context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ") + 1);//去除第一个空格到索引为一的字符串
Excute(playKey, playValue); //执行Excute方法
}
}
音符类
//音符类
class Note:Expression
{
public override void Excute(string key, double value)//重写父类Expression的Excute方法
{
string note = "";
switch (key ) //判断key内容
{
case "C":
note = "1";//表示如果获得的key是C则演奏1(do),如果是D则演奏2(Re)
break;
case "D":
note = "2";
break;
case "E":
note = "3";
break;
case "F":
note = "4";
break;
case "G":
note = "5";
break;
case "A":
note = "6";
break;
case "B":
note = "7";
break;
}
Console.Write("{0}", note); //控制台上显示
}
}
音阶类
//音阶类
class Scale :Expression
{
public override void Excute(string key, double value) //重写父类Expression的Excute方法
{
string scale = "";
switch (Convert.ToInt32(value )) //把value值转换为整数
{
case 1:
scale = "低音";//如果获得的key是O并且value是1则演奏低音,2则中音,3则高音
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
}
Console.Write("{0}", scale); //控制台上显示
}
}
四、知识点
相关知识点
①、try catch方法
②、switch case
③、substring(a,b)、substring(a)
④、IndexOf()查找字符串首次出现的位置
涉及知识点
- 抽象类
abstract关键字
可以考虑把没有实际意义的父类和没有实际意义的方法体改为抽象类抽象方法
抽象方法没有方法体
抽象类不能实例化
抽象方法必须被子类重写
参考博文