Java描述設計模式(14):解釋器模式

本文源碼:GitHub·點這裏 || GitEE·點這裏git

1、解釋器模式

一、基礎概念

解釋器模式是對象的行爲模式。給定一個語言以後,解釋器模式能夠定義出其文法的一種表示,並同時提供一個解釋器。客戶端可使用這個解釋器來解釋這個語言中的表達式。github

二、模式圖解

三、核心角色

(1)、抽象表達式正則表達式

Express:聲明具體表達式角色須要實現的抽象接口,該接口主要提供一個interpret()方法,稱作解釋操做。spring

(2)、終結符表達式express

TerminalExpress:實現抽象表達式角色接口,主要是一個interpret()方法;每一個終結符都有一個具體終結表達式與之相對應。好比解析c=a+b,a和b是終結符,解析a和b的解釋器就是終結符表達式。框架

(3)、非終結符表達式ide

NotTerminalExpress:每一條規則都須要一個具體的非終結符表達式用來銜接,通常是指運算符或者邏輯判斷,好比c=a+b,「+"就是非終結符,解析「+」的解釋器就是一個非終結符表達式。this

(4)、環境容器lua

DataMap:通常是用來存放各個終結符所對應的具體值,好比c=a+b轉換爲c=1+2。這些信息須要一個存放環境。調試

四、源代碼實現

  • 類圖結構

  • 源碼實現
public class C01_InScene {
    public static void main(String[] args) {
        DataMap dataMap = new DataMap();
        TerminalExpress terminalExpress1 = new TerminalExpress("num1");
        TerminalExpress terminalExpress2 = new TerminalExpress("num2");
        TerminalExpress terminalExpress3 = new TerminalExpress("num3");
        dataMap.putData(terminalExpress1, 1);
        dataMap.putData(terminalExpress2, 2);
        dataMap.putData(terminalExpress3, 3);
        // 1+2-3 = 0
        System.out.println(new Minus(
                           new Add(terminalExpress1,terminalExpress2), terminalExpress3)
                           .interpret(dataMap));
    }
}
// 解釋器接口
interface Express {
    Integer interpret(DataMap dataMap) ;
}
// 非終結符表達式
abstract class NotTerminalExpress implements Express {
    Express express1,express2;
    public NotTerminalExpress(Express express1, Express express2){
        this.express1 = express1;
        this.express2 = express2;
    }
}
// 終結符表達式: 1+2 終結符: 1 和 2
class TerminalExpress implements Express {
    public String field ;
    public TerminalExpress (String field){
        this.field = field ;
    }
    @Override
    public Integer interpret(DataMap dataMap) {
        return dataMap.getData(this);
    }
}
// 加法表達式
class Add extends NotTerminalExpress {
    public Add (Express e1, Express e2) {
        super(e1, e2);
    }
    // 將兩個表達式相減
    @Override
    public Integer interpret(DataMap context) {
        return this.express1.interpret(context) + this.express2.interpret(context);
    }
}
// 減法表達式
class Minus extends NotTerminalExpress {
    public Minus (Express e1, Express e2) {
        super(e1, e2);
    }
    // 將兩個表達式相減
    @Override
    public Integer interpret(DataMap context) {
        return this.express1.interpret(context) - this.express2.interpret(context);
    }
}
// 數據容器
class DataMap {
    private Map<Express,Integer> dataMap = new HashMap<>() ;
    public void putData (Express key,Integer value){
        dataMap.put(key,value) ;
    }
    public Integer getData (Express key){
        return dataMap.get(key) ;
    }
}

2、Spring框架應用

一、源碼案例

import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpringTest {
    public static void main(String[] args) {
        SpelExpressionParser parser = new SpelExpressionParser () ;
        Expression expression = parser.parseExpression("(1+3-2)*3") ;
        Integer result = (Integer)expression.getValue() ;
        System.out.println("result="+result);
    }
}

二、代碼分析

(1)Expression結構

表達式接口:具備不一樣的實現類。

interface Expression
class CompositeStringExpression implements Expression
class LiteralExpression implements Expression
class SpelExpression implements Expression

核心方法:

Object getValue() throws EvaluationException;

(2)SpelExpressionParser結構

SpelExpressionParser extends TemplateAwareExpressionParser
TemplateAwareExpressionParser implements ExpressionParser
interface ExpressionParser

(3)ExpressionParser接口

public interface ExpressionParser {
    Expression parseExpression(String var1) ;
    Expression parseExpression(String var1, ParserContext var2) ;
}

(4)Expression獲取

根據不一樣的條件獲取不一樣的Expression對象。這裏產生類的依賴關係。

源碼位置:TemplateAwareExpressionParser

public Expression parseExpression(String expressionString, 
                                  ParserContext context) 
                                  throws ParseException {
        if (context == null) {
            context = NON_TEMPLATE_PARSER_CONTEXT;
        }
        return context.isTemplate() ? 
        this.parseTemplate(expressionString, context) : 
        this.doParseExpression(expressionString, context);
    }

3、模式總結

  • 場景

編譯器、運算符表達式、正則表達式、機器人等。

  • 優勢

當有一個表達式或者語言須要解釋執行,該場景下的內容能夠考慮使用解釋器模式,使程序具備良好的擴展性。

  • 缺點

解釋器模式會引發類膨脹,會致使程序執行和調試很是複雜,不容易理解。

4、源代碼地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

相關文章
相關標籤/搜索