概念:
在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的语言,那么这些问题实例将是该语言的一些句子,这样就可以用 编译原理 中的解释器模式来实现了。
意图:
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
主要解决:
对于一些固定文法构建一个解释句子的解释器。
优点:
- 可扩展性比较好,灵活。
- 增加了新的解释表达式的方式。
- 易于实现简单文法。
缺点:
- 可利用场景比较少。
- 对于复杂的文法比较难维护。
- 解释器模式会引起类膨胀。
- 解释器模式采用递归调用方法。
实现类图
模式的结构
解释器模式实现的关键是定义文法规则、设计终结符类与非终结符类、画出结构图,必要时构建语法树,其代码结构如下:
解释器模式包含以下主要角色。
抽象表达式(Abstract Expression)角色: 定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
public interface 抽象表达式
{
public bool 解释器(string info);
}
终结符表达式(Terminal Expression)角色: 是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
using System.Collections.Generic;
public class 终结符表达式 : 抽象表达式
{ //一个用于记录终结符的哈希集
private HashSet<string> set = new HashSet<string>();
public 终结符表达式(string[] data)
{
for(int i = 0; i < data.Length; i++)
{ //记录所有终结符
set.Add(data[i]);
}
}
//解释器 判断当前是否是终结符
public bool 解释器(string info)
{
if (set.Contains(info))
{
return true;
}
return false;
}
}
非终结符表达式(Nonterminal Expression)角色: 也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
public class 非终结符表达式 : 抽象表达式
{
private 抽象表达式 mCity = null;
private 抽象表达式 mPerson = null;
public 非终结符表达式(抽象表达式 city,抽象表达式 person)
{
mCity = city;
mPerson = person;
}
public bool 解释器(string info)
{
string[] s = info.Split("的");
//解释 判断当前是否是终结符
return mCity.解释器(s[0]) && mPerson.解释器(s[1]);
}
}
环境(Context)角色: 通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
using System;
public class 优惠政策
{
private string[] countrys = {"本地","外地" };
private string[] persons = { "学生", "老人" };
private 抽象表达式 countryPerson;
public 优惠政策()
{
抽象表达式 country = new 终结符表达式(countrys);
抽象表达式 person = new 终结符表达式(persons);
countryPerson = new 非终结符表达式(country, person);
}
public void 判断优惠(string info)
{
bool b = countryPerson.解释器(info);
if (b) Console.WriteLine("您是" + info + "享受69折");
else Console.WriteLine("您不满足我们的优惠要求 但我们可以给您抹个零!");
}
}
测试:
using System;
class Program
{
static void Main(string[] args)
{
优惠政策 a = new 优惠政策();
a.判断优惠("本地的老人");
a.判断优惠("外地的打工人");
a.判断优惠("外地的学生");
a.判断优惠("外国的学生");
Console.Read();
}
}
输出示例: