設計模式の解釋器模式

?解釋器的概念其實很好理解,假如你女朋友問你你在干嘛呀,這個時候她往往是想你了。奇怪,我們獲取到的信息明明是“你在干嘛呀”,但是經過“解釋器“處理之后,就變成了“我想你了”。這下子好理解了吧,基于這個特點,解釋器模式可以構造一個可以用于創建腳本化應用的迷你語言解釋器。

那么解釋器模式到底有什么用呢?

假設現在我們做的是一個問卷調查平臺,命題人可以通過我們的平臺來設計問卷以及問卷答案。為了檢測用戶輸入的數據中是否包含答案,我們知道可以用php的正則表達式來實現,但是,一般命題人或許并不會正則表達式,所以為了方便命題人使用我們的系統,假如我們現在有一套更加容易理解的迷你語言用來設置答案,那么就能大大地提高用戶體驗。話不多說,讓我們來看看具體是怎么實現的(以下只展示解釋器部分,實際上還需要解析器部分)

現在我們 的迷你語言中包含這些語法元素,變量,字符串,and(與),equals(相等判斷).

首先我們定義一個數據存儲類,用來存放于表達式對象相關的數據

interpreterContext類

一個表達式的組成既有操作數,也有操作符。先定義一個表達式抽象基類

expression

在interpret方法中傳入interpreterContext對象是因為在對表達式對象的解釋過程中會涉及對象的存取,可以看出表達式類是依賴于interpreterContext類的。接下來定義字符串表達式類和變量表達式類,在變量表達式類中我們使用變量名作為變量表達式對象的索引,所以需要對原先抽象父類expression中的getKey方法進行重寫,同時也增加了setValue方法用于修改變量值。代碼如下:

class ?variableExpression extends expression{

? ? ? ? ? ? ? ? ? ? ? ? ? ? public $name;//變量名

? ? ? ? ? ? ? ? ? ? ? ? ? ? public $value=null;//變量值

? ? ? ? ? ? ? ? ? ? ? ? ? ? public function __construct($name,$value){

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?$this->name=$name;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?$this->value=$value;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}?

? ? ? ? ? ? ? ? ? ? ? ? ? ? public function getKey()

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return $this->name;

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ?public function ?setValue($value){

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?$this->value=$value;

? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? public function interpret(intepreterContext$context)

? ? ? ? ? ? ? ? ? ? ? ? ? ?{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(!is_null($this->value)) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $context->insert($this, $this->value);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $this->value=null;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

}

還有一點需要注意的,就是在interpret方法中插入變量名和變量值后,將該變量對象的value置空,因為如果后期定義了變量名相同的變量,則在存儲空間中該變量名索引所對應的變量值會被更新,如果這里我們沒有把已經存儲到存儲空間的變量對象的變量值屬性置空,則后期如果不小心再次調用了該變量對象的interpret方法就會修改當前值,這樣顯然是不行的。

接下來定義字符串表達式:

stringExpression類

這里字符串對象在存儲空間的索引我們采用默認的方式。

到這里我們先來簡單總結一下,可以看出操作數對象的解釋主要是將與操作數對象相關聯的數據放入存儲空間,同時為設置索引以便引用。

而對于操作符對象,我們可以將操作符對象理解為一個組合對象(二元操作符的話需要包含兩個表達式對象,注意表達式對象可以是操作符對象也可以是操作數對象)。因此,我們定義了一個抽象操作符基類。

有了該操作符抽象基類,我們就可以來定義具體的操作符類了。

下面來演示一下用法,

問題:我和你媽媽掉進水里你救誰

答案:你和媽媽。

為了設置答應,我們可以這樣來使用這個迷你語言,假設input是輸入,那么我們寫出來的語句大概是這樣子。input1 equals '你' and input2 equals '媽媽',忽略對語句進行解析的部分,我們直接跳都解釋器部分。代碼如下:

直到實例化了and操作符對象,我們這時候已經通過傳遞對象的方式成功構建了一個表達式樹,兩個equals對象分別包含了一個變量對象和一字符串對象,然后最頂層的And對象包含了兩個equals對象。當調用and對象的解釋方法時,便會隱式地調用其包含對象的解釋方法,最終將and操作結果和and對象的索引寫入存儲空間。在var_dump之后便可得到一個true。

好了,以上便是解釋器模式的基本介紹,由于水平有限未免有不當之處,歡迎指出,希望大家多多鼓勵,謝謝~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,767評論 18 399
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,969評論 19 139
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,370評論 11 349
  • 短詩六首〈夏日情懷〉 文/紅塵一凡 蛙 月色攪動荷塘 阻止不了端坐蓮臺 誦一段經文,許一個心愿 螢火蟲 暮色里來來...
    37度女人_8dda閱讀 218評論 0 1
  • 這次的作業在一拖再拖,終于完成了,畫的涂的都比較著急,經過這幾次的學習,可以拿起筆,首先定位再構圖,基本大...
    努力的妍兒閱讀 389評論 2 2