国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!

這篇具有很好參考價(jià)值的文章主要介紹了解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

解釋器模式

1.簡介

解釋器模式(Interpreter Pattern)是一種行為設(shè)計(jì)模式,它用于定義語言的文法,并且解釋語言中的表達(dá)式。在Java中,解釋器模式可以用于構(gòu)建解釋器以解析特定的語言或表達(dá)式,如數(shù)學(xué)表達(dá)式、查詢語言等。

優(yōu)點(diǎn):

  1. 靈活性: 解釋器模式可以靈活地添加新的表達(dá)式和規(guī)則,因此適用于處理不斷變化的語言或表達(dá)式。
  2. 易擴(kuò)展性: 可以輕松地?cái)U(kuò)展文法,添加新的解釋器,而不會影響現(xiàn)有的解釋器。
  3. 簡化語法分析: 將文法規(guī)則分解成一個個小的解釋器,使得語法分析更加簡單和清晰。
  4. 易于實(shí)現(xiàn): 每個表達(dá)式都可以由一個簡單的解釋器實(shí)現(xiàn),降低了系統(tǒng)的復(fù)雜度,易于實(shí)現(xiàn)和維護(hù)

缺點(diǎn):

  1. 復(fù)雜度高: 對于復(fù)雜的文法規(guī)則,需要創(chuàng)建大量的解釋器對象,可能會導(dǎo)致類爆炸問題,增加系統(tǒng)的復(fù)雜度。
  2. 執(zhí)行效率低: 解釋器模式通常采用遞歸調(diào)用的方式進(jìn)行解釋,可能會導(dǎo)致解釋過程比較耗時,執(zhí)行效率低下。
  3. 維護(hù)困難: 隨著文法的變化和解釋器的增加,維護(hù)成本可能會增加,特別是在處理復(fù)雜語言時。

使用場景:

  1. 特定領(lǐng)域語言(DSL)解析: 適用于需要解析和執(zhí)行特定領(lǐng)域語言的場景,如數(shù)學(xué)表達(dá)式、正則表達(dá)式查詢語言等。
  2. 規(guī)則引擎: 用于構(gòu)建規(guī)則引擎,根據(jù)不同的規(guī)則執(zhí)行相應(yīng)的操作。
  3. 編譯器和解釋器設(shè)計(jì): 可用于編寫編譯器和解釋器,將源代碼轉(zhuǎn)換成目標(biāo)代碼或執(zhí)行相應(yīng)的操作。
  4. 配置文件解析: 適用于解析配置文件,將配置信息轉(zhuǎn)換成相應(yīng)的對象或操作。

2.案例-生成SQL建表語句

需求描述:

假設(shè)我們需要開發(fā)一個簡單的數(shù)據(jù)庫表生成工具,它可以根據(jù)用戶提供的列信息生成相應(yīng)的 SQL 建表語句。用戶可以指定表名、列名、數(shù)據(jù)類型等信息,并且可以選擇是否設(shè)置列為主鍵、非空等約束。

用戶需求:

  1. 用戶希望能夠指定表名以及列的詳細(xì)信息,包括列名、數(shù)據(jù)類型、長度等。
  2. 用戶希望能夠選擇是否將某列設(shè)置為主鍵、非空等約束。
  3. 用戶希望能夠生成符合特定數(shù)據(jù)庫類型的建表語句,例如 PostgreSQL、MySQL 等。

實(shí)現(xiàn)思路:

  1. 定義抽象表達(dá)式接口
    • 創(chuàng)建一個接口,定義解釋方法 interpret(),該方法將返回解釋后的結(jié)果。
  2. 創(chuàng)建終結(jié)符表達(dá)式類
    • 實(shí)現(xiàn)抽象表達(dá)式接口的類,用于表示文法中的最小單元。
    • 包含需要解釋的數(shù)據(jù)和解釋方法的具體實(shí)現(xiàn)。
  3. 創(chuàng)建非終結(jié)符表達(dá)式類
    • 實(shí)現(xiàn)抽象表達(dá)式接口的類,用于表示文法中的復(fù)合結(jié)構(gòu)。
    • 包含其他表達(dá)式對象或者其他操作的組合,并實(shí)現(xiàn)解釋方法。
  4. 創(chuàng)建環(huán)境類(Context)
    • 封裝解釋器需要的數(shù)據(jù)和方法。
    • 提供執(zhí)行解釋器的方法,并返回結(jié)果。
    • 解耦解釋器與客戶端代碼: Context提供統(tǒng)一接口,客戶端代碼不需要直接操作解釋器,降低了耦合度。
    • 封裝解釋器的創(chuàng)建邏輯: Context封裝解釋器的創(chuàng)建邏輯,使客戶端代碼更簡潔,只需調(diào)用Context方法即可執(zhí)行解釋器。
    • 統(tǒng)一的異常處理機(jī)制: Context提供統(tǒng)一異常處理,捕獲解釋器執(zhí)行過程中的異常,進(jìn)行統(tǒng)一處理,如記錄日志、返回錯誤信息。
    • 支持?jǐn)U展和替換解釋器: 可以通過修改Context中的創(chuàng)建邏輯來引入新的解釋器實(shí)現(xiàn)或替換現(xiàn)有實(shí)現(xiàn),提高系統(tǒng)的靈活性和可擴(kuò)展性。
  5. 客戶端代碼
    • 創(chuàng)建具體的終結(jié)符和非終結(jié)符表達(dá)式對象。
    • 創(chuàng)建環(huán)境對象,將表達(dá)式對象傳遞給環(huán)境對象。
    • 調(diào)用環(huán)境對象的解釋方法,獲取解釋結(jié)果。

2.1.實(shí)現(xiàn)

2.1.1.抽共享表達(dá)式接口
/**
 * 定義抽象表達(dá)式接口
 * @author 13723
 * @version 1.0
 * 2024/2/6 10:01
 */
public interface Expression {
	/**
	 * 解釋方法
	 * @return 解釋結(jié)果
	 */
	String interpret();
}
2.1.2.終結(jié)符表達(dá)式類
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * 終結(jié)符實(shí)現(xiàn)類
 * 終結(jié)符(Terminal Symbol):在文法中,終結(jié)符是指不能進(jìn)一步被分解的符號或標(biāo)記。
 * 在語法分析過程中,終結(jié)符是輸入字符的最小單元。終結(jié)符是文法的基本元素,通常代表實(shí)際的詞匯或標(biāo)記。
 * 文法中的每一個終結(jié)符都有一個具體終結(jié)表達(dá)式與之相對應(yīng)。
 */
@Getter @Setter
@NoArgsConstructor
public class ColumnExpression implements Expression {
    /**
     * 列名
     */
    private String name;
    /**
     * 列類型
     */
    private String type;
    /**
     * 列長度
     */
    private String length;

    /**
     * 注釋
     */
    private String comment;

    /**
     * 是否是主鍵
     */
    private Boolean primaryKey = false;

    /**
     * 是否是非空
     */
    private Boolean notNull = false;


    public ColumnExpression(String name, String type, String length) {
        this.name = name;
        this.type = type;
        this.length = length;
    }
    public ColumnExpression(String name, String type, String length, String comment) {
        this.name = name;
        this.type = type;
        this.length = length;
        this.comment = comment;
    }
    public ColumnExpression(String name, String type, String length, String comment, Boolean notNull) {
        this.name = name;
        this.type = type;
        this.length = length;
        this.comment = comment;
        this.notNull = notNull;
    }


    public ColumnExpression(String name, String type, String length, String comment, Boolean primaryKey, Boolean notNull) {
        this.name = name;
        this.type = type;
        this.length = length;
        this.primaryKey = primaryKey;
        this.notNull = notNull;
        this.comment = comment;
    }


    @Override
    public String interpret() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t").append("\"").append(name).append("\"").append("  ").append(type).append("(").append(length).append(")");
        // 如果設(shè)置了不為空,根據(jù)數(shù)據(jù)類型添加 NOT NULL
        if (notNull) {
            if ("VARCHAR".equals(type) || "CHAR".equals(type) || "TEXT".equals(type) || "BLOB".equals(type) || "CLOB".equals(type) || "NCLOB".equals(type)){
                sb.append("  COLLATE \"pg_catalog\".\"default\" NOT NULL" );
            }else {
                sb.append(" NOT NULL");
            }
        }
        return sb.toString();
    }
}

2.1.3.非終結(jié)符表達(dá)式類
package com.hrfan.java_se_base.pattern.Interpreter_pattern.se;

import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 非終結(jié)符(Nonterminal Symbol):非終結(jié)符是可以被進(jìn)一步分解的符號或標(biāo)記,在文法規(guī)則中用來描述語言的結(jié)構(gòu)和組織。
 * 非終結(jié)符通常代表語法結(jié)構(gòu)中的一類元素,可以是語法規(guī)則的左側(cè)或右側(cè)的一部分。
 * 文法中的每條規(guī)則都對應(yīng)于一個非終結(jié)符表達(dá)式。
 */
@Getter @Setter
public class TableExpression  implements Expression{
    private String tableName;
    private List<ColumnExpression> columns;

    public TableExpression(String tableName) {
        this.tableName = tableName;
        this.columns = new ArrayList<>();
    }

    // 添加列
    public void addColumn(ColumnExpression column) {
        columns.add(column);
    }

    // 獲取設(shè)置主鍵的數(shù)據(jù)
    public List<String> getColumnPrimaryKey(){
        List<String> collect = columns.stream().filter(ColumnExpression::getPrimaryKey).map(ColumnExpression::getName).collect(Collectors.toList());
        return collect;
    }
    // 設(shè)置注釋 和 字段名稱
    public Map<String,String> getColumnComment(){
        Map<String, String> map = columns.stream().filter(it -> StringUtils.isNotBlank(it.getComment())).collect(Collectors.toMap(ColumnExpression::getName, ColumnExpression::getComment));
        return map;
    }


    @Override
    public String interpret() {
        // 獲取主鍵的列名
        List<String> columnPrimaryKey = getColumnPrimaryKey();

        StringBuilder sb = new StringBuilder("\nCREATE TABLE \"gwstd\".\"" + tableName + "\" " + "(" + "\n");
        for (int i = 0; i < columns.size(); i++) {
            // 執(zhí)行非終結(jié)符解釋邏輯
            sb.append(columns.get(i).interpret());
            if (i < columns.size() - 1 || columnPrimaryKey.size() > 0){
                sb.append(", \n");
            }
        }

        if (columnPrimaryKey.size() > 0){
            sb.append("\tCONSTRAINT ").append("\"").append(tableName).append("_pkey\"").append("PRIMARY KEY (");
            for (int i = 0; i < columnPrimaryKey.size(); i++) {
                sb.append("\"").append(columnPrimaryKey.get(i)).append("\"");
                if (i < columnPrimaryKey.size() - 1) {
                    sb.append(",");
                }
            }
            sb.append(")\n");
        }
        sb.append(");");
        // 生成輸入語句
        sb.append("\n");
        sb.append("ALTER TABLE \"gwstd\".").append("\"").append(tableName).append("\"").append(" OWNER TO \"postgres\"").append(";");


        // 生成注釋
        Map<String, String> columnComment = getColumnComment();
        if (!columnComment.isEmpty()){
            for (Map.Entry<String, String> entry : columnComment.entrySet()) {
                sb.append("\n");
                // COMMENT ON COLUMN "gwstd"."t_dec_order_head"."sid" IS '主鍵Sid';
                sb.append("COMMENT ON COLUMN \"gwstd\".").append("\"").append(tableName).append("\"").append(".").append("\"").append(entry.getKey()).append("\"").append(" IS '").append(entry.getValue()).append("';");
            }
        }


        return sb.toString();
    }
}
2.1.4.創(chuàng)建Context(承上啟下)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;

/**
 * @author 13723
 * @version 1.0
 * 2024/2/6 10:17
 */
public class Context {
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
	/**
	 * 建表語句表達(dá)式
	 */
	private Expression expression;

	public Context(){

	}
	/**
	 * 解釋方法
	 */
	public Context(Expression expression){
		this.expression = expression;
	}

	/**
	 * 執(zhí)行解釋方法
	 * @return 解釋結(jié)果
	 */
	public String interpret(){
		return expression.interpret();
	}
}

2.1.5.測試類
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;


/**
 * @author 13723
 * @version 1.0
 * 2024/2/6 10:20
 */
public class ExpressCreateTest {
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	@Test
	@DisplayName("測試建表語句解釋器")
	public void test(){
		// 創(chuàng)建表對象(使用建造者模式構(gòu)建表對象)
		TableExpressionBuilder builder = new TableExpressionBuilder("t_dec_erp_test_students");
		// 非終結(jié)符解釋器 中 添加 終結(jié)符解釋器
        // 字段名稱,字段類型,字段長度,字段注釋,是否為主鍵,是否為空
		builder.addColumn(new ColumnExpression("sid",  "VARCHAR", "11","主鍵sid",true,true))
				.addColumn(new ColumnExpression("name", "VARCHAR", "255","姓名"))
				.addColumn(new ColumnExpression("age",   "NUMERIC", "3","年齡",true))
				.addColumn(new ColumnExpression("email", "VARCHAR", "255","郵箱",true))
				.addColumn(new ColumnExpression("address", "VARCHAR", "255","聯(lián)系地址"))
				.addColumn(new ColumnExpression("telephone", "VARCHAR", "255","聯(lián)系電話"));
		// 構(gòu)建表達(dá)式
		TableExpression expression = builder.build();
		// 通過Context執(zhí)行解釋方法,獲取解釋結(jié)果.
		String interpret = new Context(expression).interpret();
		logger.error("最終生成sql:\n{}",interpret);

	}
}

解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!,spring boot,設(shè)計(jì)模式,解釋器模式

CREATE TABLE "gwstd"."t_dec_erp_test_students" (
	"sid"  VARCHAR(11)  COLLATE "pg_catalog"."default" NOT NULL, 
	"name"  VARCHAR(255), 
	"age"  NUMERIC(3) NOT NULL, 
	"email"  VARCHAR(255)  COLLATE "pg_catalog"."default" NOT NULL, 
	"address"  VARCHAR(255), 
	"telephone"  VARCHAR(255), 
	CONSTRAINT "t_dec_erp_test_students_pkey"PRIMARY KEY ("sid")
);
ALTER TABLE "gwstd"."t_dec_erp_test_students" OWNER TO "postgres";
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."address" IS '聯(lián)系地址';
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."name" IS '姓名';
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."telephone" IS '聯(lián)系電話';
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."email" IS '郵箱';
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."age" IS '年齡';
COMMENT ON COLUMN "gwstd"."t_dec_erp_test_students"."sid" IS '主鍵sid';

解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!,spring boot,設(shè)計(jì)模式,解釋器模式

解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!,spring boot,設(shè)計(jì)模式,解釋器模式

2.2.Spring使用場景

2.2.1.Spring-SpEL

Spring表達(dá)式語言(SpEL)允許在運(yùn)行時動態(tài)計(jì)算值,它可以用于配置文件、注解等多種場景中。在SpEL的背后,實(shí)際上就是使用了解釋器模式。

Spring框架中,與Spring EL(表達(dá)式語言)相關(guān)的類位于org.springframework.expression包下。以下是幾個與Spring EL密切相關(guān)的類的簡要介紹:

  1. SpelExpression: 代表一個EL表達(dá)式,它在內(nèi)部通過抽象語法樹(AST)來表示表達(dá)式。EL表達(dá)式的求值是通過調(diào)用this.ast.getValue(expressionState);來實(shí)現(xiàn)的。
  2. ExpressionParser: 表達(dá)式解析器接口,定義了解析EL表達(dá)式的方法。Spring提供了SpelExpressionParser作為默認(rèn)的表達(dá)式解析器實(shí)現(xiàn)。
  3. StandardEvaluationContext: 標(biāo)準(zhǔn)的評估上下文,用于在表達(dá)式求值期間存儲變量和函數(shù)。它提供了用于設(shè)置變量和函數(shù)的方法,這些變量和函數(shù)可以在EL表達(dá)式中使用。
  4. EvaluationContext: 評估上下文接口,用于在表達(dá)式求值期間提供變量和函數(shù)的訪問。StandardEvaluationContextEvaluationContext接口的實(shí)現(xiàn)之一。
  5. SpelNode: SpEL語法樹的節(jié)點(diǎn),代表了EL表達(dá)式的各個部分。每個節(jié)點(diǎn)都有自己的類型和操作,用于實(shí)現(xiàn)EL表達(dá)式的解析和求值。
2.2.1.1.案例代碼
@Test
@DisplayName("測試@Value")
public void test2(){
    // 1. 構(gòu)建解析器
    ExpressionParser parser = new SpelExpressionParser();
    // 2. 解析表達(dá)式
    Expression expression = parser.parseExpression("100 * 2 + 200 * 1 + 100000");
    // 3. 獲取結(jié)果
    int result = (Integer) expression.getValue();
    // 4. 打印結(jié)果
    logger.error("result:{}",result);
}

解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!,spring boot,設(shè)計(jì)模式,解釋器模式

語法樹

抽象語法樹(Abstract Syntax Tree,AST)是一種用于表示編程語言代碼結(jié)構(gòu)的樹形數(shù)據(jù)結(jié)構(gòu)

在編譯器和解釋器中,AST是一種常見的數(shù)據(jù)結(jié)構(gòu),用于表示程序代碼的語法結(jié)構(gòu)和語義信息。

在Java中,AST抽象語法樹是指代表Java源代碼結(jié)構(gòu)的樹形數(shù)據(jù)結(jié)構(gòu)。它由多個節(jié)點(diǎn)組成,每個節(jié)點(diǎn)代表源代碼中的一個語法元素,例如表達(dá)式、語句、方法調(diào)用等。AST的根節(jié)點(diǎn)表示整個程序的起始點(diǎn),而子節(jié)點(diǎn)則代表程序中的具體語法結(jié)構(gòu)。

# 語法樹        
		+
      /   \
     *     +
   /  \   /  \
  100  2  *  100000
         / \
        200  1
2.2.1.2.SpelExpression

SpelExpression 是 Spring 表達(dá)式語言(SpEL)中的一個組成部分,用于表達(dá)特定的表達(dá)式。它內(nèi)部采用抽象語法樹(AST)來表示表達(dá)式的結(jié)構(gòu)。計(jì)算表達(dá)式的值是通過調(diào)用 this.ast.getValue(expressionState); 實(shí)現(xiàn)的。在這個過程中,AST被用來解釋和執(zhí)行表達(dá)式,最終得到表達(dá)式的計(jì)算結(jié)果。

public class SpelExpression implements Expression {

    @Nullable
    public Object getValue() throws EvaluationException {
        CompiledExpression compiledAst = this.compiledAst;
        if (compiledAst != null) {
            try {
                EvaluationContext context = this.getEvaluationContext();
                return compiledAst.getValue(context.getRootObject().getValue(), context);
            } catch (Throwable var4) {
                if (this.configuration.getCompilerMode() != SpelCompilerMode.MIXED) {
                    throw new SpelEvaluationException(var4, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION, new Object[0]);
                }
            }

            this.compiledAst = null;
            this.interpretedCount.set(0);
        }

        ExpressionState expressionState = new ExpressionState(this.getEvaluationContext(), this.configuration);
        Object result = this.ast.getValue(expressionState);
        this.checkCompile(expressionState);
        return result;
    }
}
2.2.1.2.SpelNodeImpl

SpelNodeImpl 是 Spring 表達(dá)式語言(SpEL)中的關(guān)鍵類,用于表示已解析的表達(dá)式在抽象語法樹(AST)中的節(jié)點(diǎn)。

在解釋器模式中,AST 的節(jié)點(diǎn)充當(dāng)了終結(jié)符和非終結(jié)符的角色,幫助構(gòu)建表達(dá)式的結(jié)構(gòu)。

SpelNodeImpl 的子類包括以下幾種類型:

  • Literal: 代表各種類型值的父類。
  • Operator: 代表各種操作符的父類。
  • Indexer 等:代表其他類型的節(jié)點(diǎn)。
public abstract class SpelNodeImpl implements SpelNode, Opcodes {
    private static final SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0];
    protected SpelNodeImpl[] children;
    @Nullable
    private SpelNodeImpl parent;


    @Nullable
    protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
        return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), this.getValueInternal(state), desiredReturnType);
    }
	// 抽象方法子類實(shí)現(xiàn),獲取對象值
    public abstract TypedValue getValueInternal(ExpressionState expressionState) throws EvaluationException;

}

2.2.1.3.IntLiteral

IntLiteral 表示整型文字的表達(dá)式語言的ast結(jié)點(diǎn)

public class IntLiteral extends Literal {
    private final TypedValue value;

    public IntLiteral(String payload, int startPos, int endPos, int value) {
        super(payload, startPos, endPos);
        this.value = new TypedValue(value);
        this.exitTypeDescriptor = "I";
    }

    public TypedValue getLiteralValue() {
        return this.value;
    }
    // 
}
2.2.1.4.OpPlus

OpPlus 表示加法的ast結(jié)點(diǎn),在 getValueInternal 方法中對操作符兩邊進(jìn)行相加操作

public class OpPlus extends Operator {
    private static final int MAX_CONCATENATED_STRING_LENGTH = 100000;

    public OpPlus(int startPos, int endPos, SpelNodeImpl... operands) {
        super("+", startPos, endPos, operands);
        Assert.notEmpty(operands, "Operands must not be empty");
    }

    public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
        SpelNodeImpl leftOp = this.getLeftOperand();
        if (this.children.length < 2) {
            Object operandOne = leftOp.getValueInternal(state).getValue();
            if (operandOne instanceof Number) {
                if (operandOne instanceof Double) {
                    this.exitTypeDescriptor = "D";
                } else if (operandOne instanceof Float) {
                    this.exitTypeDescriptor = "F";
                } else if (operandOne instanceof Long) {
                    this.exitTypeDescriptor = "J";
                } else if (operandOne instanceof Integer) {
                    this.exitTypeDescriptor = "I";
                }

                return new TypedValue(operandOne);
            } else {
                return state.operate(Operation.ADD, operandOne, (Object)null);
            }
        } else {
			// 遞歸調(diào)用leftOp的 getValueInternal(state) ,獲取操作符左邊的值
            TypedValue operandOneValue = leftOp.getValueInternal(state);
            Object leftOperand = operandOneValue.getValue();
            // 遞歸調(diào)用children[1]的 getValueInternal(state) ,獲取操作符右邊的值
            TypedValue operandTwoValue = this.getRightOperand().getValueInternal(state);
            Object rightOperand = operandTwoValue.getValue();
            // 如果操作符左右都是數(shù)值類型,則將它們相加
            if (leftOperand instanceof Number && rightOperand instanceof Number) {
                Number leftNumber = (Number)leftOperand;
                Number rightNumber = (Number)rightOperand;
                if (!(leftNumber instanceof BigDecimal) && !(rightNumber instanceof BigDecimal)) {
                    if (!(leftNumber instanceof Double) && !(rightNumber instanceof Double)) {
                        if (!(leftNumber instanceof Float) && !(rightNumber instanceof Float)) {
                            if (!(leftNumber instanceof BigInteger) && !(rightNumber instanceof BigInteger)) {
                                if (!(leftNumber instanceof Long) && !(rightNumber instanceof Long)) {
                                    if (!CodeFlow.isIntegerForNumericOp(leftNumber) && !CodeFlow.isIntegerForNumericOp(rightNumber)) {
                                        return new TypedValue(leftNumber.doubleValue() + rightNumber.doubleValue());
                                    } else {
                                        this.exitTypeDescriptor = "I";
                                        return new TypedValue(leftNumber.intValue() + rightNumber.intValue());
                                    }
                                } else {
                                    this.exitTypeDescriptor = "J";
                                    return new TypedValue(leftNumber.longValue() + rightNumber.longValue());
                                }
                            } else {
                                BigInteger leftBigInteger = (BigInteger)NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
                                BigInteger rightBigInteger = (BigInteger)NumberUtils.convertNumberToTargetClass(rightNumber, BigInteger.class);
                                return new TypedValue(leftBigInteger.add(rightBigInteger));
                            }
                        } else {
                            this.exitTypeDescriptor = "F";
                            return new TypedValue(leftNumber.floatValue() + rightNumber.floatValue());
                        }
                    } else {
                        this.exitTypeDescriptor = "D";
                        return new TypedValue(leftNumber.doubleValue() + rightNumber.doubleValue());
                    }
                } else {
                    BigDecimal leftBigDecimal = (BigDecimal)NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
                    BigDecimal rightBigDecimal = (BigDecimal)NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
                    return new TypedValue(leftBigDecimal.add(rightBigDecimal));
                }
            } else {
                String rightString;
                String leftString;
                if (leftOperand instanceof String && rightOperand instanceof String) {
                    this.exitTypeDescriptor = "Ljava/lang/String";
                    rightString = (String)leftOperand;
                    leftString = (String)rightOperand;
                    this.checkStringLength(rightString);
                    this.checkStringLength(leftString);
                    return this.concatenate(rightString, leftString);
                } else if (leftOperand instanceof String) {
                    rightString = (String)leftOperand;
                    this.checkStringLength(rightString);
                    leftString = rightOperand == null ? "null" : convertTypedValueToString(operandTwoValue, state);
                    this.checkStringLength(leftString);
                    return this.concatenate(rightString, leftString);
                } else if (rightOperand instanceof String) {
                    rightString = (String)rightOperand;
                    this.checkStringLength(rightString);
                    leftString = leftOperand == null ? "null" : convertTypedValueToString(operandOneValue, state);
                    this.checkStringLength(leftString);
                    return this.concatenate(leftString, rightString);
                } else {
                    return state.operate(Operation.ADD, leftOperand, rightOperand);
                }
            }
        }
    }
}

解釋器模式相對于其他設(shè)計(jì)模式確實(shí)在實(shí)際應(yīng)用中使用較少,這主要是由于以下幾個原因:

  1. 復(fù)雜性和性能開銷: 解釋器模式的實(shí)現(xiàn)可能會引入較高的復(fù)雜性和性能開銷。解釋器需要對輸入進(jìn)行解析、分析和執(zhí)行,這可能導(dǎo)致性能上的損失,并且隨著解釋器規(guī)則的增多,代碼的復(fù)雜度也會增加。
  2. 不易理解和維護(hù): 解釋器模式的實(shí)現(xiàn)通常較為復(fù)雜,需要設(shè)計(jì)者對語法和語義有深入的理解,同時需要維護(hù)大量的解釋器規(guī)則。這使得解釋器模式在代碼的可讀性和可維護(hù)性方面存在挑戰(zhàn)。
  3. 有限的適用場景: 解釋器模式通常適用于特定領(lǐng)域的問題,例如編譯器、正則表達(dá)式引擎等。在許多常見的軟件開發(fā)場景中,并不經(jīng)常需要使用解釋器模式來解決問題。
  4. 其他替代方案: 對于一些需要解釋和執(zhí)行邏輯的問題,通常有更簡單、更高效的替代方案,例如使用編譯器、腳本引擎、規(guī)則引擎等。這些替代方案能夠更直接地執(zhí)行邏輯,而不需要通過解釋器的中間層。

盡管解釋器模式在一些特定的領(lǐng)域和場景下仍然有其價(jià)值,但在許多常見的軟件開發(fā)任務(wù)中,它并不是第一選擇。因此,雖然解釋器模式是一種重要的設(shè)計(jì)模式,但其應(yīng)用相對較少。文章來源地址http://www.zghlxwxcb.cn/news/detail-827284.html

到了這里,關(guān)于解鎖Spring Boot中的設(shè)計(jì)模式—02.解釋器模式:探索【解釋器模式】的奧秘與應(yīng)用實(shí)踐!的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 設(shè)計(jì)模式——解釋器模式

    設(shè)計(jì)模式——解釋器模式

    更多內(nèi)容,前往IT-BLOG 在軟件開發(fā)中,會遇到有些問題多次重復(fù)出現(xiàn),而且有一定的相似性和規(guī)律性。如果將它們歸納成一種簡單的表達(dá)式(例如:正則表達(dá)式等),那么這些問題實(shí)例將是該表達(dá)式的一些句子,這樣就可以用 “編譯原理” 中的解釋器模式來實(shí)現(xiàn)。 【1】解釋

    2024年02月03日
    瀏覽(308)
  • 設(shè)計(jì)模式(行為型模式)解釋器模式

    ?? 解釋器模式(Interpreter Pattern) 是一種行為設(shè)計(jì)模式,用于解釋特定語言或處理特定問題領(lǐng)域的語法或表達(dá)式。它定義了一種語言的語法表示,并使用該表示來解釋語言中的句子。通常用于構(gòu)建解析器、編譯器和規(guī)則評估引擎等場景。 在解釋器模式中,有以下關(guān)鍵角色:

    2024年02月20日
    瀏覽(96)
  • 設(shè)計(jì)模式詳解-解釋器模式

    類型:行為型模式 實(shí)現(xiàn)原理:實(shí)現(xiàn)了一個表達(dá)式接口,該接口使用標(biāo)識來解釋語言中的句子 作用:給定一個語言,定義它的文法表示,并定義一個解釋器,這個解釋器來解釋。 主要解決:一些重復(fù)的固定文法分別創(chuàng)建解釋器會很麻煩 何時使用:某一種特定類型的問題發(fā)生的

    2024年02月12日
    瀏覽(91)
  • 設(shè)計(jì)模式(23)解釋器模式

    設(shè)計(jì)模式(23)解釋器模式

    一、介紹: 1、定義:解釋器(Interpreter)模式是一種對象的行為模式。給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。 2、組成結(jié)構(gòu): (1)AbstractExpression(抽象表達(dá)式):約定解釋器的解釋操作,主要是一個interpret()方

    2024年02月06日
    瀏覽(99)
  • java設(shè)計(jì)模式之解釋器設(shè)計(jì)模式的前世今生

    解釋器設(shè)計(jì)模式是什么? 解釋器模式是一種行為型設(shè)計(jì)模式,它定義了一種以語法表達(dá)式的形式來表示特定規(guī)則的語言,并提供了一種解釋器來解釋這些語法表達(dá)式的實(shí)現(xiàn)方法。解釋器模式通常用于構(gòu)建編程語言、詞法分析、正則表達(dá)式、數(shù)學(xué)表達(dá)式等應(yīng)用程序。它提供了一

    2024年02月06日
    瀏覽(87)
  • 設(shè)計(jì)模式之解釋器模式筆記

    設(shè)計(jì)模式之解釋器模式筆記

    記錄下學(xué)習(xí)設(shè)計(jì)模式-解釋器模式的寫法。JDK使用版本為1.8版本。 意圖 :定義一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。 結(jié)構(gòu) : 其中: AbstractExpression 聲明一個程序的解釋操作,這個接口為抽象語法樹中所有的結(jié)點(diǎn)所

    2024年02月11日
    瀏覽(94)
  • 設(shè)計(jì)模式之解釋器模式(下)

    設(shè)計(jì)模式之解釋器模式(下)

    3)Context的作用 1.概述 在解釋器模式中,環(huán)境類Context用于存儲解釋器之外的一些全局信息,它通常作為參數(shù)被傳遞到所有表達(dá)式的解釋方法interpret()中,可以在Context對象中存儲和訪問表達(dá)式解釋器的狀態(tài),向表達(dá)式解釋器提供一些全局的、公共的數(shù)據(jù),此外還可以在Context中

    2024年04月12日
    瀏覽(91)
  • Java設(shè)計(jì)模式-解釋器模式

    Java設(shè)計(jì)模式-解釋器模式

    一、概述 如上圖,設(shè)計(jì)一個軟件用來進(jìn)行加減計(jì)算。我們第一想法就是使用工具類,提供對應(yīng)的加法和減法的工具方法。 上面的形式比較單一、有限,如果形式變化非常多,這就不符合要求,因?yàn)榧臃ê蜏p法運(yùn)算,兩個運(yùn)算符與數(shù)值可以有無限種組合方式。比如 1+2+3+4+5、

    2024年01月17日
    瀏覽(96)
  • js設(shè)計(jì)模式:解釋器模式

    js設(shè)計(jì)模式:解釋器模式

    對文本進(jìn)行解釋和編譯的時候,就會用到解釋器模式 比如你寫了一段js代碼,js引擎就會去解釋并執(zhí)行這段代碼 webpack中的各種loader就是用來解釋各種文件類型的,并將其解釋為js可識別的代碼

    2024年02月22日
    瀏覽(103)
  • 設(shè)計(jì)模式之解釋器模式(C++)

    設(shè)計(jì)模式之解釋器模式(C++)

    作者:翟天保Steven 版權(quán)聲明:著作權(quán)歸作者所有,商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處 ? ? ? ?解釋器模式是一種行為型的軟件設(shè)計(jì)模式,定義了一個解釋器,來解釋給定語言和文法的句子。也可以理解為翻譯吧,比如1+1,翻譯為一加上一,等于二,這樣就

    2024年02月02日
    瀏覽(92)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包