最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java設(shè)計模式之java解釋器模式詳解

 更新時間:2021年09月15日 10:19:27   作者:大忽悠愛忽悠  
這篇文章主要介紹了Java設(shè)計模式之解釋器模式定義與用法,結(jié)合具體實(shí)例形式詳細(xì)分析了Java解釋器模式的概念、原理、定義及相關(guān)操作技巧,需要的朋友可以參考下

介紹

解釋器模式(Interpreter Pattern):定義一個語言的文法,并且建立一個解釋器來解釋該語言中的句子,這里的 “語言” 是指使用規(guī)定格式和語法的代碼。解釋器模式是一種類行為型模式。

角色

AbstractExpression(抽象解釋器):在抽象表達(dá)式中聲明了抽象的解釋操作,具體的解釋任務(wù)由各個實(shí)現(xiàn)類完成,它是所有終結(jié)符表達(dá)式和非終結(jié)符表達(dá)式的公共父類。

TerminalExpression(終結(jié)符表達(dá)式):實(shí)現(xiàn)與文法中的元素相關(guān)聯(lián)的解釋操作,通常一個解釋器模式中只有一個終結(jié)表達(dá)式,但有多個實(shí)例,對應(yīng)不同的終結(jié)符。

NonterminalExpression(非終結(jié)符表達(dá)式):文法中的每條規(guī)則對應(yīng)于一個非終結(jié)表達(dá)式,非終結(jié)符表達(dá)式根據(jù)邏輯的復(fù)雜程度而增加,原則上每個文法規(guī)則都對應(yīng)一個非終結(jié)符表達(dá)式

Context(環(huán)境類):環(huán)境類又稱為上下文類,它用于存儲解釋器之外的一些全局信息,通常它臨時存儲了需要解釋的語句。

客戶類(Test): 客戶端,解析表達(dá)式,構(gòu)建抽象語法樹,執(zhí)行具體的解釋操作等.

在這里插入圖片描述

計算器案例

環(huán)境類,存儲解釋器之外的一些全局信息,通常它臨時存儲了需要解釋的語句

public class Context
{
    private Map<Expression, Integer> map = new HashMap<>();
    //定義變量
    public void add(Expression s, Integer value)
    {
        map.put(s, value);
    }
    //將變量轉(zhuǎn)換成數(shù)字
    public int lookup(Expression s){
        return map.get(s);
    }
}

解釋器接口

public interface Expression
{
    int interpreter(Context context);//一定會有解釋方法
}

抽象非終結(jié)符表達(dá)式

public abstract class NonTerminalExpression implements Expression{
    Expression e1,e2;
    public NonTerminalExpression(Expression e1, Expression e2){
        this.e1 = e1;
        this.e2 = e2;
    }
}

減法表達(dá)式實(shí)現(xiàn)類

public class MinusOperation extends NonTerminalExpression {
    public MinusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }
    //將兩個表達(dá)式相減
    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) - this.e2.interpreter(context);
    }
}

加法表達(dá)式實(shí)現(xiàn)類

public class PlusOperation extends NonTerminalExpression {
    public PlusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }
    //將兩個表達(dá)式相加
    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) + this.e2.interpreter(context);
    }
}

終結(jié)符表達(dá)式(在這個例子,用來存放數(shù)字,或者代表數(shù)字的字符)

public class TerminalExpression implements Expression{
    String variable;
    public TerminalExpression(String variable){
        this.variable = variable;
    }
    //獲得該變量的值
    @Override
    public int interpreter(Context context) {
        return context.lookup(this);
    }
}

測試:

public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        TerminalExpression a = new TerminalExpression("a");
        TerminalExpression b = new TerminalExpression("b");
        TerminalExpression c = new TerminalExpression("c");
        context.add(a, 4);
        context.add(b, 8);
        context.add(c, 2);
           //new PlusOperation(a,b).interpreter(context)--->返回12
        // c.interpreter(context)--->2
        //MinusOperation(12,2)..interpreter(context)--->10
        System.out.println(new MinusOperation(new PlusOperation(a,b), c).interpreter(context));
    }
}

在這里插入圖片描述

UML圖

在這里插入圖片描述

深入挖掘

非終結(jié)符表達(dá)式(相當(dāng)于樹的樹杈):在這個例子中就是相加,相減的表達(dá)式,稱為非終結(jié)符,這是非常形象的,因?yàn)楫?dāng)運(yùn)算遇到這類的表達(dá)式的時候,必須先把非終結(jié)符的結(jié)果計算出來,猶如剝繭一般,一層一層的調(diào)用,就比如上面的

new MinusOperation(new PlusOperation(a,b), c).interpreter(context)

這個MinusOperation左邊參數(shù)是new PlusOperation(a,b),是非終結(jié)符表達(dá)式,所以要調(diào)用PlusOperation,因?yàn)?code>PlusOperation的左右兩邊都是TerminalExpression,是終結(jié)符表達(dá)式,所以計算然后返回,到最外面的MinusOperation函數(shù),發(fā)現(xiàn)右邊c是終結(jié)符表達(dá)式,所以可以計算。

終結(jié)符表達(dá)式(相當(dāng)于樹的葉子):遇到這個表達(dá)式interpreter執(zhí)行能直接返回結(jié)果,不會向下繼續(xù)調(diào)用。

構(gòu)建的語法樹

在這里插入圖片描述

葉子節(jié)點(diǎn)即為終結(jié)符,樹杈即為非終結(jié)符,遇到非終結(jié)符要繼續(xù)往下解析,遇到終結(jié)符則返回。a+b-c(4+8-2)

上面的語法樹是手動建的(new MinusOperation(new PlusOperation(a,b), c).interpreter(context)),實(shí)際情況,客戶輸入的都是(4+8-2)這樣的式子,所以,接下來寫的就是解析的輸入式子然后自動構(gòu)建語法樹,然后計算結(jié)果.

public class Context {
    private Map<Expression, Integer> map = new HashMap<>();
    public void add(Expression s, Integer value){
        map.put(s, value);
    }
    public Integer lookup(Expression s){
        return map.get(s);
    }
    //構(gòu)建語法樹的主要方法
    public static Expression build(String str) {
        //主要利用棧來實(shí)現(xiàn)
        Stack<Expression> objects = new Stack<>();
        for (int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            //遇到運(yùn)算符號+號時候
            if (c == '+'){
                //先出棧
                Expression pop = objects.pop();
                //將運(yùn)算結(jié)果入棧
                objects.push(new PlusOperation(pop, new TerminalExpression(String.valueOf(str.charAt(++i)))));
            } else if (c == '-'){
                //遇到減號類似加號
                Expression pop = objects.pop();
                objects.push(new MinusOperation(pop, new TerminalExpression(String.valueOf(str.charAt(++i)))));
            } else {
                //遇到非終結(jié)符直接入棧(基本就是第一個數(shù)字的情況)
                objects.push(new TerminalExpression(String.valueOf(str.charAt(i))));
            }
        }
        //把最后的棧頂元素返回
        return objects.pop();
    }
}


public class TerminalExpression implements Expression {
    String variable;
    public TerminalExpression(String variable){
        this.variable = variable;
    }
    @Override
    public int interpreter(Context context) {
        //因?yàn)橐嫒葜暗陌姹?
        Integer lookup = context.lookup(this);
        if (lookup == null)
            //若在map中能找到對應(yīng)的數(shù)則返回
            return Integer.valueOf(variable);
        //找不到則直接返回(認(rèn)為輸入的就是數(shù)字)
        return lookup;
    }
}

public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        TerminalExpression a = new TerminalExpression("a");
        TerminalExpression b = new TerminalExpression("b");
        TerminalExpression c = new TerminalExpression("c");
        String str = "4+8-2+9+9-8";
        Expression build = Context.build(str);
        System.out.println("4+8-2+9+9-8=" + build.interpreter(context));
        context.add(a, 4);
        context.add(b, 8);
        context.add(c, 2);
        System.out.println(new MinusOperation(new PlusOperation(a,b), c).interpreter(context));
    }
}

解釋器模式總結(jié)

解釋器模式為自定義語言的設(shè)計和實(shí)現(xiàn)提供了一種解決方案,它用于定義一組文法規(guī)則并通過這組文法規(guī)則來解釋語言中的句子。雖然解釋器模式的使用頻率不是特別高,但是它在正則表達(dá)式、XML文檔解釋等領(lǐng)域還是得到了廣泛使用。

主要優(yōu)點(diǎn)

  • 易于改變和擴(kuò)展文法。由于在解釋器模式中使用類來表示語言的文法規(guī)則,因此可以通過繼承等機(jī)制來改變或擴(kuò)展文法。
  • 每一條文法規(guī)則都可以表示為一個類,因此可以方便地實(shí)現(xiàn)一個簡單的語言。
  • 實(shí)現(xiàn)文法較為容易。在抽象語法樹中每一個表達(dá)式節(jié)點(diǎn)類的實(shí)現(xiàn)方式都是相似的,這些類的代碼編寫都不會特別復(fù)雜,還可以通過一些工具自動生成節(jié)點(diǎn)類代碼。
  • 增加新的解釋表達(dá)式較為方便。如果用戶需要增加新的解釋表達(dá)式只需要對應(yīng)增加一個新的終結(jié)符表達(dá)式或非終結(jié)符表達(dá)式類,原有表達(dá)式類代碼無須修改,符合"開閉原則"。

主要缺點(diǎn)

  • 對于復(fù)雜文法難以維護(hù)。在解釋器模式中,每一條規(guī)則至少需要定義一個類,因此如果一個語言包含太多文法規(guī)則,類的個數(shù)將會急劇增加,導(dǎo)致系統(tǒng)難以管理和維護(hù),此時可以考慮使用語法分析程序等方式來取代解釋器模式。
  • 執(zhí)行效率較低。由于在解釋器模式中使用了大量的循環(huán)和遞歸調(diào)用,因此在解釋較為復(fù)雜的句子時其速度很慢,而且代碼的調(diào)試過程也比較麻煩。

適用場景

  • 可以將一個需要解釋執(zhí)行的語言中的句子表示為一個抽象語法樹。
  • 一些重復(fù)出現(xiàn)的問題可以用一種簡單的語言來進(jìn)行表達(dá)。
  • 一個語言的文法較為簡單。
  • 對執(zhí)行效率要求不高。

解釋器模式的典型應(yīng)用

Spring EL表達(dá)式中的解釋器模式

在下面的類圖中,Expression是一個接口,相當(dāng)于我們解釋器模式中的非終結(jié)符表達(dá)式,而ExpressionParser相當(dāng)于終結(jié)符表達(dá)式。根據(jù)不同的Parser對象,返回不同的Expression對象

在這里插入圖片描述

Expression接口:

//抽象的非終結(jié)符表達(dá)式
public interface Expression {
	Object getValue() throws EvaluationException;
	Object getValue(Object rootObject) throws EvaluationException;
}

SpelExpression類:

//具體的非終結(jié)符表達(dá)式
public class SpelExpression implements Expression {
	@Override
	public Object getValue() throws EvaluationException {
		Object result;
		if (this.compiledAst != null) {
			try {
				TypedValue contextRoot = evaluationContext == null ? null : evaluationContext.getRootObject();
				return this.compiledAst.getValue(contextRoot == null ? null : contextRoot.getValue(), evaluationContext);
			}
			catch (Throwable ex) {
				// If running in mixed mode, revert to interpreted
				if (this.configuration.getCompilerMode() == SpelCompilerMode.MIXED) {
					this.interpretedCount = 0;
					this.compiledAst = null;
				}
				else {
					// Running in SpelCompilerMode.immediate mode - propagate exception to caller
					throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION);
				}
			}
		}
		ExpressionState expressionState = new ExpressionState(getEvaluationContext(), this.configuration);
		result = this.ast.getValue(expressionState);
		checkCompile(expressionState);
		return result;
	}
}

CompositeStringExpression:

//具體的非終結(jié)符表達(dá)式
public class CompositeStringExpression implements Expression {
	@Override
	public String getValue() throws EvaluationException {
		StringBuilder sb = new StringBuilder();
		for (Expression expression : this.expressions) {
			String value = expression.getValue(String.class);
			if (value != null) {
				sb.append(value);
			}
		}
		return sb.toString();
	}
}

ExpressionParser接口:

public interface ExpressionParser {
	//解析表達(dá)式
	Expression parseExpression(String expressionString) throws ParseException;
	Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
}

TemplateAwareExpressionParser類:

public abstract class TemplateAwareExpressionParser implements ExpressionParser {
	@Override
	public Expression parseExpression(String expressionString) throws ParseException {
		return parseExpression(expressionString, NON_TEMPLATE_PARSER_CONTEXT);
	}
	//根據(jù)不同的parser返回不同的Expression對象
	@Override
	public Expression parseExpression(String expressionString, ParserContext context)
			throws ParseException {
		if (context == null) {
			context = NON_TEMPLATE_PARSER_CONTEXT;
		}
		if (context.isTemplate()) {
			return parseTemplate(expressionString, context);
		}
		else {
			return doParseExpression(expressionString, context);
		}
	}
	private Expression parseTemplate(String expressionString, ParserContext context)
			throws ParseException {
		if (expressionString.length() == 0) {
			return new LiteralExpression("");
		}
		Expression[] expressions = parseExpressions(expressionString, context);
		if (expressions.length == 1) {
			return expressions[0];
		}
		else {
			return new CompositeStringExpression(expressionString, expressions);
		}
	}
	//抽象的,由子類去實(shí)現(xiàn)
	protected abstract Expression doParseExpression(String expressionString,
			ParserContext context) throws ParseException;
}

SpelExpressionParser類:

public class SpelExpressionParser extends TemplateAwareExpressionParser {
	@Override
	protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException {
		//這里返回了一個InternalSpelExpressionParser,
		return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
	}
}

InternalSpelExpressionParser類:

class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
	@Override
	protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException {
		try {
			this.expressionString = expressionString;
			Tokenizer tokenizer = new Tokenizer(expressionString);
			tokenizer.process();
			this.tokenStream = tokenizer.getTokens();
			this.tokenStreamLength = this.tokenStream.size();
			this.tokenStreamPointer = 0;
			this.constructedNodes.clear();
			SpelNodeImpl ast = eatExpression();
			if (moreTokens()) {
				throw new SpelParseException(peekToken().startPos, SpelMessage.MORE_INPUT, toString(nextToken()));
			}
			Assert.isTrue(this.constructedNodes.isEmpty());
			return new SpelExpression(expressionString, ast, this.configuration);
		}
		catch (InternalParseException ex) {
			throw ex.getCause();
		}
	}
}

參考文章

解釋器模式

設(shè)計模式(二十)解釋器模式

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Idea安裝及涉及springboot詳細(xì)配置的圖文教程

    Idea安裝及涉及springboot詳細(xì)配置的圖文教程

    這篇文章主要介紹了Idea安裝及涉及springboot詳細(xì)配置,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 使用SpringBoot簡單了解Druid的監(jiān)控系統(tǒng)的配置方法

    使用SpringBoot簡單了解Druid的監(jiān)控系統(tǒng)的配置方法

    這篇文章主要介紹了使用SpringBoot簡單了解Druid的監(jiān)控系統(tǒng)的配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • springboot清除字符串前后空格與防xss攻擊方法

    springboot清除字符串前后空格與防xss攻擊方法

    這篇文章主要介紹了springboot清除字符串前后空格與防xss攻擊方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java類和對象原理與用法分析

    java類和對象原理與用法分析

    這篇文章主要介紹了java類和對象原理與用法,結(jié)合實(shí)例形式分析了java類和對象的相關(guān)概念、功能、原理、使用技巧與操作注意事項,需要的朋友可以參考下
    2020-02-02
  • 解析spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class

    解析spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class

    這篇文章主要介紹了spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Java Scaner類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Java Scaner類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Java.util.Scanner是Java5.0的新特征,主要功能是簡化文本掃描。下面通過本文給大家分享java scaner類相關(guān)知識,需要的朋友下吧
    2017-04-04
  • SpringBoot整合Spring Security構(gòu)建安全的Web應(yīng)用

    SpringBoot整合Spring Security構(gòu)建安全的Web應(yīng)用

    pring Security是一個強(qiáng)大的身份驗(yàn)證和訪問控制框架,本文主要介紹了SpringBoot整合Spring Security構(gòu)建安全的Web應(yīng)用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • java高級用法之注解和反射講義

    java高級用法之注解和反射講義

    這篇文章主要給大家介紹了關(guān)于java高級用法之注解和反射講義的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • java 遍歷Map及Map轉(zhuǎn)化為二維數(shù)組的實(shí)例

    java 遍歷Map及Map轉(zhuǎn)化為二維數(shù)組的實(shí)例

    這篇文章主要介紹了java 遍歷Map及Map轉(zhuǎn)化為二維數(shù)組的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-08-08
  • 詳解SpringBoot Controller接收參數(shù)的幾種常用方式

    詳解SpringBoot Controller接收參數(shù)的幾種常用方式

    這篇文章主要介紹了詳解SpringBoot Controller接收參數(shù)的幾種常用方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10

最新評論

抚顺市| 甘肃省| 潮安县| 伊川县| 黄平县| 兴隆县| 石屏县| 拉萨市| 安丘市| 丹凤县| 富平县| 应用必备| 天台县| 化州市| 舟山市| 吉林市| 温泉县| 仁怀市| 芜湖县| 五常市| 惠水县| 长汀县| 定西市| 梧州市| 湟源县| 项城市| 麻阳| 当涂县| 南召县| 冀州市| 罗山县| 布拖县| 舟曲县| 常熟市| 宁国市| 昌图县| 怀来县| 兴和县| 深水埗区| 永安市| 依安县|