概念
解释器模式就是按照给定的语法,进行解析。给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
实现
案例:小明饭店举行了一个促销活动,凡是到店的顾客名字包含“明”字,或者
籍贯为广州的都可以享受半价优惠,每当顾客进店都需要到门口的电脑上进行身份登记,输入格式为:深圳,阿花
直接上代码:
首先我们定义一个抽象表达式类:
public interface AbstractExpression {
public boolean interpret(String info); //解释方法
}
然后对抽象表达式进行具体实现,我们输入的字符串中,逗号是不需要进行解析的,所以我们把逗号之前,与逗号之后的字段分隔开,包含逗号时,改字符串为非终结符表达式类:
//非终结符表达式类
public class AndExpression implements AbstractExpression {
private AbstractExpression city = null;
private AbstractExpression name = null;
public AndExpression(AbstractExpression city, AbstractExpression name) {
this.city = city;
this.name = name;
}
@Override
public boolean interpret(String info) {
//把输入的字符串切分成两份,以逗号分隔开
String str[] = info.split(",");
//判断籍贯是否为广州
boolean IsCity = city.interpret(str[0]);
//判断名字是否包含明
boolean IsName = name.interpret(str[1]);
if(IsCity || IsName){
return true;
}
return false;
}
}
切分完两段终结符表达式后,我们得到两段终结符表达式:
//终结符表达式类
public class TerminalExpression implements AbstractExpression {
private String key;
public TerminalExpression(String key) {
this.key = key;
}
@Override
public boolean interpret(String info) {
if(key.contains(info)){
return true;
}
return false;
}
}
准备工作已经做好了,那么就需要定义一个环境类,填入需要的关键词:
//环境类
public class Context {
//定义籍贯关键词
private String cityKey = "广州";
//定义名字关键词
private String key = "明";
private AbstractExpression city;
private AbstractExpression name;
private AbstractExpression rule;
public Context(){
city = new TerminalExpression(cityKey);
name = new TerminalExpression(key);
rule = new AndExpression(city,name);
}
//判断顾客是否能享受半价
public void IsHalf(String info){
//对输入信息进行判断
boolean result = rule.interpret(info);
if(result){
System.out.println("恭喜您,获得半价优惠!");
}else{
System.out.println("很遗憾,你与本次优惠条件不符ㄒoㄒ");
}
}
}
最后就是我们的测试类:
public class Main {
public static void main(String[] args) {
//实例环境类
Context context = new Context();
String p1 = "深圳,阿花";
String p2 = "北京,康熙";
String p3 = "上海,乾隆";
String p4 = "广州,郭明强";
String p5 = "新疆,尔明";
String p6 = "广州,二百五";
context.IsHalf(p1);
context.IsHalf(p2);
context.IsHalf(p3);
context.IsHalf(p4);
context.IsHalf(p5);
context.IsHalf(p6);
}
}
测试结果:
优点:有较好的扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了
缺点:容易产生类膨胀,使维护变得复杂, 其次,解释器模式采用递归调用方法。每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道终的结果,必须一层一层的剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂,用于解析复杂、冗长的语法时,效率是难以忍受的
本文参考:《设计模式之禅》
本文的代码:https://pan.baidu.com/s/1nVvYZaqoNUT700LRLFQrkg
提取码:vx8y