1. 程式人生 > >原始的解釋器模式(Interpreter Pattern)

原始的解釋器模式(Interpreter Pattern)

乘除 情況 詳細 strong com n) img mes 相關

解釋器模式的定義(現實項目中非常少遇到,因此直接理論先。。。)

解釋器模式是一種依照規定語法進行解析的方案,在如今項目中使用較少,其定義為:給定一門語言,定義它的方法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。

其構成例如以下:

1、AbstractExpression——抽象解釋器

詳細的解釋任務由各個實現類完畢。詳細的解釋器分別由TerminalExpression和NonterminalExpression完畢

2、TerminalExpression——終結符表達式

實現與方法中的元素相關聯的解釋操作。通過一個解釋器模式中僅僅有一個終結符表達式,但有多個實例,相應不同的終結符。

3、NonterminalExpression——非終結符表達式

文法中的每條規則相應於一個非終結表達式。非終結符表達式依據邏輯的復雜程序而添加,原則上每一個文法規則相應一個非終結符表達式。

4、Context——環境角色

那如今用解釋器模式來解釋一下四則運算(加減乘除)。類圖例如以下:

技術分享
圖中MathExpression為抽象解釋器,Literal、Variable為終結符表達式,Sum、Multiply為非終結符表達式。結構非常清晰。實現代碼例如以下:

<?php

interface MathExpression
{
    public function evaluate( array $values );
}

/**
 * A terminal expression which is a literal value.
 */
class Literal implements MathExpression
{
    private $_value;

    public function __construct( $value ) {
        $this->_value = $value;
    }

    public function evaluate( array $values ) {
        return $this->_value;
    }
}

/**
 * A terminal expression which represents a variable.
 */
class Variable implements MathExpression
{
    private $_letter;

    public function __construct( $letter ) {
        $this->_letter = $letter;
    }

    public function evaluate( array $values ) {
        return $values[$this->_letter];
    }
}

/**
 * Nonterminal expression.
 */
class Sum implements MathExpression
{
    private $_a;
    private $_b;

    public function __construct( MathExpression $a, MathExpression $b ) {
        $this->_a = $a;
        $this->_b = $b;
    }

    public function evaluate( array $values ) {
        return $this->_a->evaluate( $values ) + $this->_b->evaluate( $values );
    }
}

/**
 * Nonterminal expression.
 */
class Multiply implements MathExpression
{
    private $_a;
    private $_b;

    public function __construct( MathExpression $a, MathExpression $b ) {
        $this->_a = $a;
        $this->_b = $b;
    }

    public function evaluate( array $values ) {
        return $this->_a->evaluate( $values ) * $this->_b->evaluate( $values );
    }
}

// 10(a + 3)
$expression = new Multiply( new Literal( 10 ), new Sum( new Variable( ‘a‘ ), new Literal( 3 ) ) );
echo $expression->evaluate( array( ‘a‘ => 111 ) ), "\n";

執行結果:1140
[Finished in 0.1s]

我們來看看這麽寫的優缺點

解釋器模式的長處

解釋器模式是一個簡單語法分析工具,它最顯著的長處就是擴展性。改動語法規則僅僅要改動對應的非終結符表達式就能夠了,若擴展語法,則僅僅要添加非終結符類就能夠了。

解釋器模式的缺點

1、解釋器模式會引起類膨脹(感覺好多模式都有這個問題啊)

每一個語法都要產生一個非終結符表達式,語法規則比較復雜時,就能夠產生大量的類文件,為維護帶來了許多的麻煩。

2、解釋器模式採用遞歸調用方法

每一個終結符表達式僅僅關心與自己有關的表達式,每一個表達式須要知道終於的結果。必須一層一層地剝繭。不管是面向過程的語言還是面向對象的語言,遞歸都是在必要條件下使用的,它導致調試很復雜。

3、效率問題

有遞歸自然就會有效率問題,特別是用於解釋復雜冗長的語法時。

解釋器模式的使用場景

1、反復發生的問題能夠使用解釋器模式

比如server日誌的分析處理,因為各個server的日誌模式不同。可是數據要素是同樣的,依照解釋器模式的說法就是終結符表達式都是同樣的,可是非終結符表達式就須要制定了。

2、一個簡單語法須要解釋的場景

比如 SQL語法分析

解釋器模式的註意事項

盡量不要在重要的模塊中使用解釋器模式,否則維護會是一個非常大的問題。在項目中能夠使用shell,JRuby,Groovy等腳本語言取代解釋器模式,彌補php效率上的不足。

一般在大中型的框架型項目可以找到它的身影,如一些數據分析工具。報表設計工具,科學計算工具等。若你確實遇到“一種特定類型的問題發生的頻率足夠高”的情況,準備使用解釋器模式時,可以考慮一下Expression4J,MESP,Jep等開源的解析工具包,功能都異常強大,不是必需自己從頭編寫解釋器。


原始的解釋器模式(Interpreter Pattern)