最近在看 “深入PHP面向?qū)ο竽J脚c實(shí)踐” ,學(xué)習(xí)書(shū)中的內(nèi)容后瞬間覺(jué)得自己有點(diǎn)高大上了,哈 ! 其實(shí)還是個(gè)菜B。相信也會(huì)有新手朋友在看這本(我自己也是新手),對(duì)書(shū)中我個(gè)人認(rèn)為比較難的內(nèi)容的學(xué)習(xí)心得就想拿出來(lái)分享和交流,1是希望對(duì)自己所學(xué)知識(shí)能夠起到鞏固和加深理解的作用 2是希望對(duì)看到本文且感興趣的新手朋友一些幫助。
這部分內(nèi)容看了好幾遍了代碼也跟著敲了幾遍,估計(jì)本文想要實(shí)現(xiàn)的功能大概就是用戶在web頁(yè)面上輸入一些內(nèi)容,然后通過(guò)后臺(tái)程序解析后進(jìn)行回復(fù)(感覺(jué)就是在廢話)。例如我在前臺(tái)web頁(yè)面輸入框里輸入:
$input = "4";$input equals "4" or $input equals "four";
然后提交,系統(tǒng)就會(huì)回復(fù)類似 “條件成立” 或者 “條件不成立”的結(jié)果(有點(diǎn)類似直接在前臺(tái)寫(xiě)代碼并運(yùn)行,后臺(tái)解析后會(huì)返回一個(gè)結(jié)果。原書(shū)中雖然沒(méi)有講解整個(gè)前臺(tái)輸入到后臺(tái)解析的過(guò)程但我猜這個(gè)后臺(tái)解析應(yīng)該還有一個(gè)使用正則表達(dá)式提取類似上面2行代碼中關(guān)鍵字的過(guò)程)
上面這二行代碼雖然是作者發(fā)明的語(yǔ)言,但根據(jù)字面含義也不難理解,第一行是定義一個(gè)變量并賦值,第二行是對(duì)變量進(jìn)行一個(gè)判斷(變量等于4或者等于four)。
廢話不多說(shuō)來(lái)看看這個(gè)模式定義的這幾個(gè)類 (類圖請(qǐng)自行看原文):
一、interpreterContext 這個(gè)類就像一個(gè)容器 主要是用來(lái)存放和獲取需要進(jìn)行比較的值和比較的結(jié)果的,例如上述代碼中的4, four,和比較結(jié)果 “true”或“false”,保存的形式是數(shù)組即類的屬性$expressionstore,代碼如下:
class InterpreterContext{ private $expressionstore = array(); //存放比較的值和結(jié)果 function replace(Expression $exp,$value){ // 設(shè)置值 $this->expressionstore[$exp->getKey()] = $value; } function lookup(Expression $exp){ //獲取值 return $this->expressionstore[$exp->getKey()]; }}
這個(gè)類就像一個(gè)工具,供其他類來(lái)使用(它和其他類不存在繼承、組合或聚合的關(guān)系)。
二、Expression 這是一個(gè)表達(dá)式的抽象類,定義了抽象方法interpret() 和方法getKey()
代碼如下:
abstract class Expression { private static $keycount = 0; //計(jì)數(shù)用的 private $key; //存放一個(gè)唯一值 //主要實(shí)現(xiàn)將前臺(tái)獲取到的數(shù)據(jù)存放到上述InterpreterContext類中的功能,看到下面的內(nèi)容就會(huì)發(fā)現(xiàn)繼承他的類調(diào)用了InterpreterContext類的replace()方法 abstract function interpret (InterpreterContext $context); //獲取一個(gè)唯一值 function getKey(){ if(!isset($this->key)){ self::$keycount++; $this->key= self::$keycount; } return $this->key; }}
下面將要講到的類都將繼承這個(gè)類,并且他和OperatorExpression(操作符表達(dá)式抽象類)是一個(gè)組合的關(guān)系,也就是說(shuō)OperatorExpression在初始化時(shí)可以包含所有繼承了Expression的子類(這也是本書(shū)一直在強(qiáng)調(diào)的要面向接口編程,這個(gè)Expression就是個(gè)接口,利用這個(gè)接口可以實(shí)現(xiàn)多態(tài),不知道自己裝B說(shuō)的對(duì)不對(duì),哈! 具體可以在看看原書(shū)的類圖)
三、LiteralExpression 文字表達(dá)式類,作用就是將一個(gè)字符串保存到InterpreterContext這個(gè)小容器里,保存成一個(gè)索引數(shù)組,例如保存開(kāi)頭那二句自創(chuàng)代碼中的 4 或者 four
代碼如下:
class LiteralExpression extends Expression{ private $value; function __construct ($value){ //初始化時(shí)傳入要保存的值 $this->value= $value; } function interpret(InterpreterContext $context){ //調(diào)用InterpreterContext類的replace()將$value保存到InterpreterContext這個(gè)小容器里 $context->replace($this,$this->value); }}
四、VariableExpression 變量表達(dá)式類,和上面類的作用是一樣的只不過(guò)數(shù)據(jù)將被保存成關(guān)聯(lián)數(shù)組,關(guān)聯(lián)數(shù)組中的健是變量名,值呢就是變量的值,例如開(kāi)頭二句中的變量"input" 和值 "4",
代碼如下:
class VariableExpression extends Expression{ private $name; //變量名 private $val; //變量值 function __construct ($name,$val=null){ $this->name = $name; $this->val = $val; } function interpret(InterpreterContext $context){ if(!is_null($this->val)){ $context->replace($this,$this->val); $this->val = null; } } function setValue($value){ //用于設(shè)置變量的值 $this->val = $value; } function getKey(){ //這個(gè)復(fù)寫(xiě)了父類的getKey()方法,在小容器InterpreterContext的lookup()方法調(diào)用這個(gè)類的實(shí)例的getKey()方法時(shí) 它將返回一個(gè)字符串(即變量名)而不是數(shù)字索引 return $this->name; }}
五、OperatorExpression 操作符表達(dá)式抽象基類,此類繼承且組合了Expression抽象基類,實(shí)現(xiàn)的interpret()方法主要保存表達(dá)式的計(jì)算結(jié)果
代碼如下:
abstract class OperatorExpression extends Expression{protected $l_op; //表達(dá)式左邊的值protected $r_op; //表達(dá)式右邊的值function __construct (Expression $l_op,Expression $r_op){ //初始化時(shí)可組合繼承了Expression類的子類實(shí)例$this->l_op = $l_op;$this->r_op = $r_op;}function interpret(InterpreterContext $context){ //主要用于保存表達(dá)試的結(jié)果(保存到InterpreterContext 類的實(shí)例中)$this->l_op->interpret($context); //將Expression子類實(shí)例的值或計(jì)算結(jié)果保存到InterpreterContext 類的實(shí)例中$this->r_op->interpret($context);$result_l = $context->lookup($this->l_op); //獲取上一步的值或計(jì)算結(jié)果$result_r = $context->lookup($this->r_op);$this->doInterpret($context,$result_l,$result_r); //具體的比較運(yùn)算由繼承的子類來(lái)實(shí)現(xiàn)}protected abstract function doInterpret(InterpreterContext $context,$result_l,$result_r);}
六、EqualsExpression、BooleanOrExpression、BooleanAndExpression,分別為繼承了OperatorExpression 抽象基類的相等表達(dá)式、或表達(dá)式、與表達(dá)式只有一個(gè)方法doInterpret()內(nèi)部調(diào)用了InterpreterContext類的replace()方法將表達(dá)式的計(jì)算結(jié)果保存到InterpreterContext類的實(shí)例中
代碼如下:
//相等表達(dá)式class EqualsExpression extends OperatorExpression {protected function doInterpret(InterpreterContext $context,$result_l,$result_r){$context->replace($this,$result_l == $result_r);}}//或表達(dá)式class BooleanOrExpression extends OperatorExpression{protected function doInterpret(InterpreterContext $context,$result_l,$result_r){$context->replace($this,$result_l || $result_r);}}//與表達(dá)式class BooleanAndExpression extends OperatorExpression{protected function doInterpret(InterpreterContext $context,$result_l,$result_r){$context->replace($this,$result_l && $result_r);}}
到此為止此模式相關(guān)的類就介紹完畢,上述代碼都是進(jìn)過(guò)測(cè)試的,可直接復(fù)制粘貼運(yùn)行來(lái)查看結(jié)果,現(xiàn)在我們就來(lái)看看客戶端代碼:
客戶端代碼一:
$context = new InterpreterContext();$statement = new BooleanOrExpression ( //可嘗試將此操作符表達(dá)式換成BooleanAndExpression 運(yùn)行一下 看看執(zhí)行結(jié)果//可嘗試將LiteralExpression中實(shí)例化的參數(shù)改成其他值看看運(yùn)算結(jié)果,或者直接將EqualsExpression對(duì)象換成BooleanOrExpression 或BooleanAndExpression new EqualsExpression(new LiteralExpression('four'),new LiteralExpression('four')), new EqualsExpression(new LiteralExpression('b'),new LiteralExpression('4')));$statement->interpret($context);if($context->lookup($statement)){echo '條件成立';} else {echo '條件不成立';}
客戶端代碼二:
$context = new InterpreterContext();$statement = new BooleanOrExpression(new BooleanAndExpression(new EqualsExpression(new LiteralExpression('4'),new LiteralExpression('4')),new EqualsExpression(new LiteralExpression('4'),new LiteralExpression('4'))),new EqualsExpression(new LiteralExpression('b'),new LiteralExpression('4')));$statement->interpret($context);if($context->lookup($statement)){echo '條件成立';} else {echo '條件不成立';}
客戶端代碼三:
這是原文的客戶端代碼實(shí)例和上述客戶端代碼的區(qū)別在于使用了變量表達(dá)式VariableExpression
$context = new InterpreterContext(); $input = new VariableExpression('input'); //這里定義了一個(gè)變量input 但并未賦值$statement = new BooleanOrExpression(new EqualsExpression($input,new LiteralExpression('four')), //這里變量表達(dá)式和文字表達(dá)式的值將進(jìn)行一個(gè)是否相等的比較new EqualsExpression($input,new LiteralExpression('4')));foreach (array("four","4","52") as $val){$input->setValue($val); //對(duì)input這個(gè)變量賦值print "變量input的值為:$val:<br/>";$statement->interpret($context); //進(jìn)行比較并將比較結(jié)果存入InterpreterContext對(duì)象實(shí)例if($context->lookup($statement)){ //獲取比較的結(jié)果print "條件成立 <br/>";} else {print "條件不成立 <br/>";}}
上述代碼經(jīng)過(guò)測(cè)試都可以正常運(yùn)行,有需要的朋友可以復(fù)制下來(lái),運(yùn)行一下看看結(jié)果。
以上就是PHP解釋器模式用法詳解的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注 其它相關(guān)文章!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。
新聞熱點(diǎn)
疑難解答
圖片精選