Interpreter 解釋器模式
解釋器模式:
定義一個語言的文法,並且建立一個解釋器來解釋該語言中的句子,這裏的“語言”是指使用規定格式和語法的代碼。
解釋器模式是一種類行爲型模式。 由於表達式可分爲終結符表達式和非終結符表達式,
因此解釋器模式的結構與組合模式的結構有些類似,但在解釋器模式中包含更多的組成元素。結構圖:
示例類圖:
示例代碼:
// Expression
public interface Expression {
public void interpret(Context context);
}
// AbstractExpression
public abstract class AbstractExpression implements Expression {
protected static List<String> table;
public AbstractExpression() {
if (null == table) {
initTable();
}
}
public void initTable() {
table = new ArrayList<String>();
table.add("一");
table.add("二");
table.add("三");
table.add("四");
table.add("五");
table.add("六");
table.add("七");
table.add("八");
table.add("九");
}
public void interpret(Context context) {
String statement = context.getStatement();
System.out.println(statement);
if (null == statement || statement.isEmpty())
return;
for (int i = 0; i < table.size(); i++) {
String tail = table.get(i) + this.getPostfix();
// 從低位往高位分析,即從右往左
if (statement.endsWith(tail)) {
int newData = context.getData() + (i + 1) * this.multiplier();
context.setData(newData);
context.setStatement(statement.substring(0, statement.length() - tail.length()));
}
if (statement.endsWith("零")) {
context.setStatement(statement.substring(0, statement.length() - "零".length()));
}
}
}
// 表達式的後綴是以什麼表示的 十,百,千...
public abstract String getPostfix();
// 表達式的數量級
public abstract int multiplier();
}
// TerminalExpression 個位數解釋器
public class ExpressionGe extends AbstractExpression {
@Override
public String getPostfix() {
return "";
}
@Override
public int multiplier() {
return 1;
}
}
// TerminalExpression 十位數解釋器
public class ExpressionShi extends AbstractExpression {
@Override
public String getPostfix() {
return "十";
}
@Override
public int multiplier() {
return 10;
}
}
// TerminalExpression 百位數解釋器
public class ExpressionBai extends AbstractExpression {
@Override
public String getPostfix() {
return "百";
}
@Override
public int multiplier() {
return 100;
}
}
// TerminalExpression 千位數解釋器
public class ExpressionQian extends AbstractExpression {
@Override
public String getPostfix() {
return "千";
}
@Override
public int multiplier() {
return 1000;
}
}
// NonterminalExpression 萬位數解釋器
public class ExpressionWan extends AbstractExpression {
private static List<Expression> expressions = new ArrayList<Expression>();
public ExpressionWan() {
if (expressions.isEmpty()) {
expressions.add(new ExpressionGe());
expressions.add(new ExpressionShi());
expressions.add(new ExpressionBai());
expressions.add(new ExpressionQian());
}
}
@Override
public void interpret(Context context) {
String statement = context.getStatement();
if (null == statement || statement.isEmpty())
return;
if (statement.endsWith(this.getPostfix())) {
context.setStatement(statement.substring(0, statement.length() - getPostfix().length()));
int data = context.getData();
context.setData(0);// 置零
for (Expression expression : expressions) {
expression.interpret(context);
}
context.setData(data + this.multiplier() * context.getData());
}
}
@Override
public String getPostfix() {
return "萬";
}
@Override
public int multiplier() {
return 10000;
}
}
// 將中文數字串由低位向高位方向不斷轉化
public class Convertor {
private static List<Expression> expressions = new ArrayList<Expression>();
public Convertor() {
if (expressions.isEmpty()) {
expressions.add(new ExpressionGe());
expressions.add(new ExpressionShi());
expressions.add(new ExpressionBai());
expressions.add(new ExpressionQian());
expressions.add(new ExpressionWan());
}
}
public int convert(String chineseNum) {
Context context = new Context(chineseNum);
for (Expression expression : expressions) {
expression.interpret(context);
}
return context.getData();
}
}
// 測試
public class ExpressionTest {
public static void main(String[] args) {
String chineseNum = "六百三十七萬八千二百零一";// 6378201
Convertor convertor = new Convertor();
System.out.println(chineseNum);
System.out.println(convertor.convert(chineseNum));
System.out.println(convertor.convert("五百萬"));
}
}
Context:上下文,通常包含各個解釋器需要的數據或是公共的功能。
這個Context在解釋器模式中起着非常重要的作用。
一般用來傳遞被所有解釋器共享的數據,後面的解釋器可以從這裏獲取這些值。AbstractExpression: 定義解釋器的接口/抽象類,約定解釋器的解釋操作。
其中的Interpret接口,正如其名字那樣,它是專門用來解釋該解釋器所要實現的功能。
(如加法解釋器中的Interpret接口就是完成兩個操作數的相加功能)。TerminalExpression: 終結符解釋器,用來實現語法規則中和終結符相關的操作,
不再包含其他的解釋器,如果用組合模式來構建抽象語法樹的話,
就相當於組合模式中的葉子對象,可以有多種終結符解釋器。NonterminalExpression: 非終結符解釋器,用來實現語法規則中非終結符相關的操作,
通常一個解釋器對應一個語法規則,可以包含其他解釋器,如果用組合模式構建抽象語法樹的話,
就相當於組合模式中的組合對象。可以有多種非終結符解釋器。- 缺點:
執行效率較低。由於在解釋器模式中使用了大量的循環和遞歸調用,
因此在解釋較爲複雜的句子時其速度很慢,而且代碼的調試過程也比較麻煩。對於複雜文法難以維護。在解釋器模式中,每一條規則至少需要定義一個類,
因此如果一個語言包含太多文法規則,類的個數將會急劇增加,導致系統難以管理和維護,
此時可以考慮使用語法分析程序等方式來取代解釋器模式。