最近在看 “深入PHP面向對象模式與實踐” ,學習書中的內容后瞬間覺得自己有點高大上了,哈 ! 其實還是個菜。相信也會有新手朋友在看這本(我自己也是新手),對書中我個人認為比較難的內容的學習心得就想拿出來分享和交流,1是希望對自己所學知識能夠起到鞏固和加深理解的作用 2是希望對看到本文且感興趣的新手朋友一些幫助。
這部分內容看了好幾遍了代碼也跟著敲了幾遍,估計本文想要實現的功能大概就是用戶在web頁面上輸入一些內容,然后通過后臺程序解析后進行回復(感覺就是在廢話)。例如我在前臺web頁面輸入框里輸入:
$input="4";
$inputequals"4"or$inputequals"four";
然后提交,系統就會回復類似 “條件成立” 或者 “條件不成立”的結果(有點類似直接在前臺寫代碼并運行,后臺解析后會返回一個結果。原書中雖然沒有講解整個前臺輸入到后臺解析的過程但我猜這個后臺解析應該還有一個使用正則表達式提取類似上面2行代碼中關鍵字的過程)
上面這二行代碼雖然是作者發明的語言,但根據字面含義也不難理解,第一行是定義一個變量并賦值,第二行是對變量進行一個判斷(變量等于4或者等于four)。
廢話不多說來看看這個模式定義的這幾個類 (類圖請自行看原文):
一、interpreterContext 這個類就像一個容器主要是用來存放和獲取需要進行比較的值和比較的結果的,例如上述代碼中的4, four,和比較結果 “true”或“false”,保存的形式是數組即類的屬性$expressionstore,代碼如下:
- classInterpreterContext{
- private$expressionstore=array();//存放比較的值和結果
- functionreplace(Expression$exp,$value){ // 設置值
- $this->expressionstore[$exp->getKey()] =$value;
- }
- functionlookup(Expression$exp){ //獲取值
- return$this->expressionstore[$exp->getKey()];
- }
- }
這個類就像一個工具,供其他類來使用(它和其他類不存在繼承、組合或聚合的關系)。
二、Expression 這是一個表達式的抽象類,定義了抽象方法interpret() 和方法getKey(),代碼如下:
- abstractclassExpression {
- privatestatic$keycount= 0; //計數用的
- private$key; //存放一個唯一值
主要實現將前臺獲取到的數據存放到上述InterpreterContext類中的功能,看到下面的內容就會發現繼承他的類調用了InterpreterContext類的replace()方法:
- abstractfunctioninterpret (InterpreterContext$context);
- /獲取一個唯一值
- functiongetKey(){
- if(!isset($this->key)){
- self::$keycount++;
- $this->key= self::$keycount;
- }
- return$this->key;
- }
下面將要講到的類都將繼承這個類,并且他和OperatorExpression(操作符表達式抽象類)是一個組合的關系,也就是說OperatorExpression在初始化時可以包含所有繼承了Expression的子類(這也是本書一直在強調的要面向接口編程,這個Expression就是個接口,利用這個接口可以實現多態,不知道自己裝B說的對不對,哈! 具體可以在看看原書的類圖)
三、LiteralExpression 文字表達式類,作用就是將一個字符串保存到InterpreterContext這個小容器里,保存成一個索引數組,例如保存開頭那二句自創代碼中的 4 或者 four,代碼如下:
- classLiteralExpressionextendsExpression{
- private$value;
- function__construct ($value){ //初始化時傳入要保存的值
- $this->value=$value;
- }
- functioninterpret(InterpreterContext$context){ //調用InterpreterContext類的replace()將$value保存到InterpreterContext這個小容器里
- $context->replace($this,$this->value);
- }
- }
四、VariableExpression 變量表達式類,和上面類的作用是一樣的只不過數據將被保存成關聯數組,關聯數組中的健是變量名,值呢就是變量的值,例如開頭二句中的變量"input" 和值 "4",代碼如下:
- classVariableExpressionextendsExpression{
- private$name; //變量名
- private$val; //變量值
- function__construct ($name,$val=null){
- $this->name =$name;
- $this->val =$val;
- }
- functioninterpret(InterpreterContext$context){
- if(!is_null($this->val)){
- $context->replace($this,$this->val);
- $this->val = null;
- }
- }
- functionsetValue($value){ //用于設置變量的值
- $this->val =$value;
- }
- functiongetKey(){ //這個復寫了父類的getKey()方法,在小容器InterpreterContext的lookup()方法調用這個類的實例的getKey()方法時 它將返回一個字符串(即變量名)而不是數字索引
- return$this->name;
- }
- }
五、OperatorExpression 操作符表達式抽象基類,此類繼承且組合了Expression抽象基類,實現的interpret()方法主要保存表達式的計算結果,代碼如下:
- abstractclassOperatorExpressionextendsExpression{
- protected$l_op; //表達式左邊的值
- protected$r_op; //表達式右邊的值
- function__construct (Expression$l_op,Expression$r_op){ //初始化時可組合繼承了Expression類的子類實例
- $this->l_op =$l_op;
- $this->r_op =$r_op;
- }
- functioninterpret(InterpreterContext$context){ //主要用于保存表達試的結果(保存到InterpreterContext 類的實例中)
- $this->l_op->interpret($context); //將Expression子類實例的值或計算結果保存到InterpreterContext 類的實例中
- $this->r_op->interpret($context);
- $result_l=$context->lookup($this->l_op); //獲取上一步的值或計算結果
- $result_r=$context->lookup($this->r_op);
- $this->doInterpret($context,$result_l,$result_r); //具體的比較運算由繼承的子類來實現
- }
- protectedabstractfunctiondoInterpret(InterpreterContext$context,$result_l,$result_r);
- }
六、EqualsExpression、BooleanOrExpression、BooleanAndExpression,分別為繼承了OperatorExpression 抽象基類的相等表達式、或表達式、與表達式只有一個方法doInterpret()內部調用了InterpreterContext類的replace()方法將表達式的計算結果保存到InterpreterContext類的實例中,代碼如下:
- //相等表達式
- classEqualsExpressionextendsOperatorExpression {
- protectedfunctiondoInterpret(InterpreterContext$context,$result_l,$result_r){
- $context->replace($this,$result_l==$result_r);
- }
- }
- //或表達式
- classBooleanOrExpressionextendsOperatorExpression{
- protectedfunctiondoInterpret(InterpreterContext$context,$result_l,$result_r){
- $context->replace($this,$result_l||$result_r);
- }
- }
- //與表達式
- classBooleanAndExpressionextendsOperatorExpression{
- protectedfunctiondoInterpret(InterpreterContext$context,$result_l,$result_r){
- $context->replace($this,$result_l&&$result_r);
- }
- }
到此為止此模式相關的類就介紹完畢,上述代碼都是進過測試的,可直接復制粘貼運行來查看結果,現在我們就來看看客戶端代碼:
客戶端代碼一:
- $context=newInterpreterContext();
- $statement=newBooleanOrExpression ( //可嘗試將此操作符表達式換成BooleanAndExpression 運行一下 看看執行結果
- //可嘗試將LiteralExpression中實例化的參數改成其他值看看運算結果,或者直接將EqualsExpression對象換成BooleanOrExpression 或BooleanAndExpression
- newEqualsExpression(newLiteralExpression('four'),newLiteralExpression('four')),
- newEqualsExpression(newLiteralExpression('b'),newLiteralExpression(?'))
- );
- $statement->interpret($context);
- if($context->lookup($statement)){
- echo'條件成立'
- }else{
- echo'條件不成立'
- }
客戶端代碼二:
- $context=newInterpreterContext();
- $statement=newBooleanOrExpression(
- newBooleanAndExpression(
- newEqualsExpression(newLiteralExpression(?'),newLiteralExpression(?')),
- newEqualsExpression(newLiteralExpression(?'),newLiteralExpression(?'))
- ),
- newEqualsExpression(newLiteralExpression('b'),newLiteralExpression(?'))
- );
- $statement->interpret($context);
- if($context->lookup($statement)){
- echo'條件成立'
- }else{
- echo'條件不成立'
- }
客戶端代碼三:
這是原文的客戶端代碼實例和上述客戶端代碼的區別在于使用了變量表達式VariableExpression
- $context=newInterpreterContext();
- $input=newVariableExpression('input'); //這里定義了一個變量input 但并未賦值
- $statement=newBooleanOrExpression(
- newEqualsExpression($input,newLiteralExpression('four')), //這里變量表達式和文字表達式的值將進行一個是否相等的比較
- newEqualsExpression($input,newLiteralExpression(?'))
- );
- foreach(array("four","4","52")as$val){
- $input->setValue($val); //對input這個變量賦值
- print"變量input的值為:$val:
- ";
- $statement->interpret($context); //進行比較并將比較結果存入InterpreterContext對象實例
- if($context->lookup($statement)){ //獲取比較的結果
- print"條件成立
- ";
- }else{
- print"條件不成立
- ";
- }
- }
上述代碼經過測試都可以正常運行,有需要的朋友可以復制下來,運行一下看看結果。
以上這篇PHP面向對象的解釋器模式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持本網站。
新聞熱點
疑難解答