解釋器模式:
定義一個語言的文法,而且創建一個解釋器來解釋該語言中的句子,這裏的「語言」是指使用規定格式和語法的代碼。
解釋器模式是一種類行爲型模式。 因爲表達式可分爲終結符表達式和非終結符表達式,
所以解釋器模式的結構與組合模式的結構有些相似,但在解釋器模式中包含更多的組成元素。java
結構圖:
express
示例類圖:
markdown
示例代碼:ide
// 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接口就是完成兩個操做數的相加功能)。this
TerminalExpression: 終結符解釋器,用來實現語法規則中和終結符相關的操做,
再也不包含其餘的解釋器,若是用組合模式來構建抽象語法樹的話,
就至關於組合模式中的葉子對象,能夠有多種終結符解釋器。spa
NonterminalExpression: 非終結符解釋器,用來實現語法規則中非終結符相關的操做,
一般一個解釋器對應一個語法規則,能夠包含其餘解釋器,若是用組合模式構建抽象語法樹的話,
就至關於組合模式中的組合對象。能夠有多種非終結符解釋器。調試
執行效率較低。因爲在解釋器模式中使用了大量的循環和遞歸調用,
所以在解釋較爲複雜的句子時其速度很慢,並且代碼的調試過程也比較麻煩。code
對於複雜文法難以維護。在解釋器模式中,每一條規則至少須要定義一個類,
所以若是一個語言包含太多文法規則,類的個數將會急劇增長,致使系統難以管理和維護,
此時能夠考慮使用語法分析程序等方式來取代解釋器模式。對象