解釋器是一種用的比較少的行為模式,其提供了一種解釋語(yǔ)言的語(yǔ)法,或者表達(dá)式的方式。該模式定義了一個(gè)表達(dá)式的接口
案例(3乘7乘5除以3)
- 抽象接口
/**
* 抽象接口
*/
public interface Node {
int interpret();
}
- 非終結(jié)符抽象接口
public abstract class SymbolNode implements Node {
protected Node left;
protected Node right;
public SymbolNode(Node left, Node right) {
this.left = left;
this.right = right;
}
}
- 終結(jié)符
*終結(jié)符
*/
public class ValueNode implements Node{
private int value;
public ValueNode(int value) {
this.value = value;
}
@Override
public int interpret() {
return value;
}
}
- 具體的計(jì)算操作交由子類去實(shí)現(xiàn)
//乘法的計(jì)算
public class MulNode extends SymbolNode {
public MulNode(Node left, Node right) {
super(left, right);
}
/**
* 計(jì)算方法(乘法)
* @return
*/
@Override
public int interpret() {
return left.interpret()*right.interpret();
}
}
//除法計(jì)算
public class DivNode extends SymbolNode{
public DivNode(Node left, Node right) {
super(left, right);
}
/**
* 計(jì)算方法(除法)
* @return
*/
@Override
public int interpret() {
return left.interpret()/right.interpret();
}
}
- 計(jì)算的過程
public class Caculator {
public int build(String num){
Node left=null;
Node right=null;
Node lastNode=null;
String[] statemnts=num.split(" ");
for(int i=0;i<statemnts.length;i++){
if("*".equalsIgnoreCase(statemnts[i])){//乘法
left=lastNode;
int val=Integer.parseInt(statemnts[++i]);
right=new ValueNode(val);
lastNode=new MulNode(left,right);
}else if("/".equalsIgnoreCase(statemnts[i])){//除法
left=lastNode;
int val=Integer.parseInt(statemnts[++i]);
right=new ValueNode(val);
lastNode=new DivNode(left,right);
}else if("%".equalsIgnoreCase(statemnts[i])){
left=lastNode;
int val=Integer.parseInt(statemnts[++i]);
right=new ValueNode(val);
lastNode=new ModeNode(left,right);
} else {
lastNode=new ValueNode(Integer.parseInt(statemnts[i]));
}
}
return lastNode.interpret();
}
}
- 客戶端的調(diào)用
String content="3 * 5 * 7 / 3 % 30";
Caculator caculator=new Caculator();
int num=caculator.build(content);
System.out.print("最后的結(jié)果為:"+num);
- 結(jié)果
最后的結(jié)果為:5
- 總結(jié):
應(yīng)用場(chǎng)景:
1. 簡(jiǎn)單的語(yǔ)言需要解釋執(zhí)行而且可以將該語(yǔ)言中的語(yǔ)句表示一個(gè)抽象的語(yǔ)法樹
2. 對(duì)于某個(gè)特定的領(lǐng)域出現(xiàn)的不斷重復(fù)的問題扰藕,可以轉(zhuǎn)換成一種語(yǔ)法規(guī)則下的語(yǔ)句
** 優(yōu)缺點(diǎn):**
優(yōu)點(diǎn): 每個(gè)語(yǔ)法都要產(chǎn)生一個(gè)非終結(jié)符表達(dá)式槽奕,語(yǔ)法規(guī)則比較復(fù)雜時(shí),就可能產(chǎn)生大量的類文件败晴,為維護(hù)帶來了非常多的麻煩浓冒。
缺點(diǎn):
1. 解釋器模式采用遞歸調(diào)用方法 每個(gè)非終結(jié)符表達(dá)式只關(guān)心與自己有關(guān)的表達(dá)式,每個(gè)表達(dá)式需要知道最終的結(jié)果尖坤,必須一層一層地剝繭稳懒,無論是面向過程的語(yǔ)言還是面向?qū)ο蟮恼Z(yǔ)言,遞歸都是在必要條件下使用的慢味,它導(dǎo)致調(diào)試非常復(fù)雜场梆。想想看墅冷,如果要排查一個(gè)語(yǔ)法錯(cuò)誤,我們是不是要一個(gè)一個(gè)斷點(diǎn)的調(diào)試下去或油,直到最小的語(yǔ)法單元寞忿。
2. 解釋器模式由于使用了大量的循環(huán)和遞歸,效率是個(gè)不容忽視的問題顶岸,特別是用于解析復(fù)雜罐脊、冗長(zhǎng)的語(yǔ)法時(shí),效率是難以忍受的蜕琴。
最后:
解釋器模式在實(shí)際的開發(fā)中使用的非常少萍桌,因?yàn)樗鼤?huì)引起效率、性能以及維護(hù)等問題凌简,一般在大中型的框架型項(xiàng)目能夠找到它的身影上炎,比如一些數(shù)據(jù)分析工具、報(bào)表設(shè)計(jì)工具雏搂、科學(xué)計(jì)算工具等等藕施,若你確實(shí)遇到“一種特定類型的問題發(fā)生的頻率足夠高”的情況,準(zhǔn)備使用解釋器模式時(shí)凸郑,可以考慮一下Expression4J裳食、MESP(Math Expression String Parser)、Jep等開源的解析工具包