1 介绍
Acey:考试临近了,你复习的怎么样啦?小白。
小白:😮,word哥呀,真的好险呀,考了三门了,都是飘过的你造嘛!
Acey: 你这是考场老司机呀,专注60分一辈子,多一分就是浪费呀是吧?
小白:
Acey:好吧,不说你了,后面的科目可别挂了😇。今天呢,我们来用解释器模式来算算你一共考了多少分。
小白:那我用计算器算不就好了。,,ԾㅂԾ,,
Acey:那显得多low呀,简单的四则运算当然可以用计算器,但是当以后用到更复杂的运算时计算器就解决不了,所以为了以后,现在要好好的学。
小白:好啵。
解释器模式:Interpreter 模式是行为模式的一种。简单的说就是一种语法解释器架构。
Acey:说的通俗易懂一点。我们在使用计算器的时候,通常就是按下相应的数字和运算符,然后结果就显示出来了,整个被隐藏起来的运算过程就是对应的解释器的解释过程。而对于我们要算的总成绩也是一个道理,我们只需要将科目及对应的分数输入,经过解释器的解释,我们就可以得到我们想要的结果,这就是解释器模式。
小白:这样呀,那如果我们要进行规模比较大的运算,如 统计,预测之类的,使用解释器模式会不会比较影响效率哇。🤣
Acey:会呢,因为我们是采用递归调用的方式,所以如果程序需要高效的话,建议就不要使用了。
2 实现
首先,我们先来看看结构类图
其中
- AbstractExpression 是一个抽象表达式类,具体的解释任务由各个实现类完成。
- TerminalExpression是终结符表达式类,实现相关的解释操作(获取当前科目分数)
- NonterminalExpression 是非终结符表达式类,每条规则对应于一个非终结表达式(相应的运算)
- Context是上下文角色,用来存储输入的数据(科目及分数)。
实现
第一步:创建抽象表达式角色
Expression.class
//抽象表达式角色
public abstract class Expression {
public abstract Integer result(Context context);
}
第二步:创建上下文角色
Context.class
//上下文角色,使用HashMap来存储变量及其对应的值
public class Context {
//用于保存科目及相应的分数
private Map<Subject,Integer> score = new HashMap<>();
//为每门课填充分数
public void addScore(Subject subject, Integer score){
this.score.put(subject, score);
}
//获取科目对应的分数
public Integer getScore(Subject subject){
return this.score.get(subject);
}
}
第三步:创建终结符角色
Subject.class
//终结符表达式角色
public class Subject extends Expression{
//从context(Map)中获取当前科目的分数
@Override
public Integer result(Context context) {
return context.getScore(this);
}
}
第四步:创建非终结符角色
Add.class
//非终结者表达式角色
public class Add extends Expression{
private Expression left;
private Expression right;
//传入两门科目名称
public Add(Expression left, Expression right) {
this.left = left;
this.right = right;
}
//计算结果
@Override
public Integer result(Context context) {
return left.result(context) + right.result(context);
}
}
第五步:测试
Mainclass.class
public class MainClass {
public static void main(String[] args) {
//容器,存放科目及其对应分数
Context context = new Context();
//创建科目
Subject math = new Subject();
Subject chinese = new Subject();
Subject english = new Subject();
//保存分数
context.addScore(math, 61);
context.addScore(chinese, 60);
context.addScore(english, 65);
//迭代计算总分数
Expression result = new Add(new Add(math, chinese), english) ;
System.out.println("总分数为:" + result.result(context));
}
}
Acey:上述代码中只实现了一个非终结符表达式,当然根据需求可以很轻易的添加,它的优点就是拓展性强。但是缺点也是很明显的,每条规则(运算符)都要对应一个非终结符表达式,当业务复杂时,存在大量的非终结符表达式,那维护起来就相当麻烦了。模式中使用了递归也是一个不容小觑的缺点,当运行解释冗长、复杂的语句时效率往往是很低的,也不利于开发人的调试。所以在开发中解释器模式一般也很少用到。
last
祝大家
喜欢的话戳一下喜欢呗。
有什么建议的话希望大家能在下方回复😋
上一篇:《适配器模式 - 我有金卡,你有麽?》
下一篇:《中介者模式 - 听说你还是单身dog》