解释器模式
1.应用实例
英雄联盟中每个英雄都有自己的属性,比如英雄性别,英雄类型,英雄攻击类型,英雄别名等;
当我们要解释英雄各个属性的时候就可以用到解释器模式;
1.首先先定义一个英雄抽象类,有一个抽象方法。
public abstract class Hero {//建立英雄语法树
public abstract String interpret(String hero);//该方法是用来被其他类(解释器)继承用来解释英雄属性的
}
2.定义一个英雄性别类继承Hero类
public class HeroGender extends Hero {
@Override
public String interpret(String hero) {//解释英雄性别
if(hero.equals("寒冰射手"))
return "女";
else if(hero.equals("德玛西亚之力"))
return "男";
else if(hero.equals("流浪法师"))
return "男";
else if(hero.equals("影流之主"))
return "男";
else if(hero.equals("放逐之刃"))
return "女";
else {
return "还未设定该英雄性别";
}
}
}
3.定义一个英雄类型类继承Hero类
public class HeroType extends Hero {
@Override
public String interpret(String hero) {//解释英雄类型
if(hero.equals("寒冰射手"))
return "射手";
else if(hero.equals("德玛西亚之力"))
return "坦克";
else if(hero.equals("流浪法师"))
return "法师";
else if(hero.equals("影流之主"))
return "刺客";
else if(hero.equals("放逐之刃"))
return "战士";
else{
return "还未设定该英雄类型";
}
}
}
4.定义一个英雄别名类继承Hero类
public class HeroAlias extends Hero {
@Override
public String interpret(String hero) {//解释英雄别名
if(hero.equals("寒冰射手"))
return "蛮王老婆";
else if(hero.equals("德玛西亚之力"))
return "草丛之王";
else if(hero.equals("流浪法师"))
return "光头";
else if(hero.equals("影流之主"))
return "儿童劫";
else if(hero.equals("放逐之刃"))
return "锐萌萌";
else {
return "还未设定该英雄别名";
}
}
}
5.测试类
public class Test {
public static void main(String[] args) {
Hero h1 = new HeroAlias();//创建解释英雄别名的解释器对象
Hero h2 = new HeroGender();//创建解释英雄性别的解释器对象
Hero h3 = new HeroType();//创建解释英雄类型的解释器对象
String hero1 = "寒冰射手";
//分别用解释器来解释hero1的别名,性别,类型
System.out.println(h1.interpret(hero1));//蛮王老婆
System.out.println(h2.interpret(hero1));//女
System.out.println(h3.interpret(hero1));//射手
System.out.println("-------");
String hero2 = "影流之主";
System.out.println(h1.interpret(hero2));//儿童劫
System.out.println(h2.interpret(hero2));//男
System.out.println(h3.interpret(hero2));//刺客
System.out.println("-------");
String hero3 = "盲僧";
System.out.println(h1.interpret(hero3));//还未设定该英雄别名
System.out.println(h2.interpret(hero3));//还未设定该英雄性别
System.out.println(h3.interpret(hero3));//还未设定该英雄类型
}
}
我们还可以自己定义许多类继承Hero类作为解释器来解释一些关于英雄的属性或其他等等;
2.解释器的概念
解释器(Interpreter)模式的定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
3.为什么会有解释器模式
解释器可以在Java语言之上再定义一层语言,这种语言通过Java编写的解释器可以放到Java环境中去执行,这样如果用户的需求发生变化,比如打算做其他事情的时候,只用在自己定义的新的语言上进行修改,对于Java编写的代码不需要进行任何的修改就能在Java环境中运行,这是非常有用的。这就好像,虽然不管怎么编译,最终由中间代码生成最终代码(机器码)是依赖于相应的机器的。但是编译器却能理解高级语言和低级语言,无论高级语言的程序是怎么样编写的,编译器的代码是不用修改的,而解释器模式就是想做一个建立在Java和我们自定义语言之间的编译器。
4.解释器的应用场景
1.当语言的文法较为简单,且执行效率不是关键问题时。
2.当问题重复出现,且可以用一种简单的语言来进行表达时。
3.当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。
5.总结:解释器的优缺点
优点:
1.易于改变和扩展文法;
2.每一条文法规则都可以表示为一个类,因此可以方便地实现每一个简单的语言。
3.实现文法比较容易。
缺点:
1.执行效率低,解释很复杂的句子时速度很慢(像刚刚举的实例中我们完全可以进行属性封装来解决问题,而不用每个属性都需要创建一个解释器类而变得很复杂)
2.对于复杂文法难以维护,再解释模式下每一条规则至少定义一个类,因此如果太复杂无法处理。
3.解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能等问题。如果碰到对表达式的解释,在 Java 中可以用 Expression4J 或 Jep 等来设计。