首頁  >  文章  >  後端開發  >  PHP解釋器模式用法詳解

PHP解釋器模式用法詳解

巴扎黑
巴扎黑原創
2017-08-23 13:41:262101瀏覽

下面小編就為大家帶來一篇老生常談PHP物件導向之解釋器模式。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧

最近在看 “深入PHP物件導向模式與實踐” ,學習書中的內容後瞬間覺得自己有點高大上了,哈 ! 其實還是個菜B。相信也會有新手朋友在看這本(我自己也是新手),對書中我個人認為比較難的內容的學習心得就想拿出來分享和交流,1是希望對自己所學知識能夠起到鞏固和加深理解的作用2是希望對看到本文且有興趣的新手朋友一些幫助。

這部分內容看了好幾遍了程式碼也跟著敲了幾遍,估計本文想要實現的功能大概就是用戶在web頁面上輸入一些內容,然後透過後台程式解析後回覆(感覺就是在廢話)。例如我在前台web頁面輸入框裡輸入:


$input = "4";
$input equals "4" or $input equals "four";

然後提交,系統就會回覆類似「條件成立」 或「條件不成立」的結果(有點類似直接在前台寫程式碼並運行,後台解析後會回傳一個結果。關鍵字的過程)

上面這二行程式碼雖然是作者發明的語言,但根據字面意義也不難理解,第一行是定義一個變數並賦值,第二行是對變數進行一個判斷(變數等於4或等於four)。

廢話不多說來看看這個模式定義的這幾個類別(類別圖請自行看原文):

一、interpreterContext 這個類別就像一個容器主要是用來存放和取得需要進行比較的值和比較的結果的,例如上述程式碼中的4, four,和比較結果「true」或「false」,保存的形式是數組即類別的屬性$expressionstore,程式碼如下:


class InterpreterContext{
  private $expressionstore = array(); //存放比较的值和结果
  
  function replace(Expression $exp,$value){    // 设置值
    $this->expressionstore[$exp->getKey()] = $value;
  }
  
  function lookup(Expression $exp){        //获取值
    return $this->expressionstore[$exp->getKey()];
  }
}

這個類別就像一個工具,供其他類別來使用(它和其他類別不存在繼承、組合或聚合的關係)。

二、Expression 這是一個表達式的抽象類別,定義了抽象方法interpret() 和方法getKey()

程式碼如下:


abstract class Expression {
  private static $keycount = 0;  //计数用的
  private $key;          //存放一个唯一值


  //主要实现将前台获取到的数据存放到上述InterpreterContext类中的功能,看到下面的内容就会发现继承他的类调用了InterpreterContext类的replace()方法
  abstract function interpret (InterpreterContext $context); 

 //获取一个唯一值  
  function getKey(){       
    if(!isset($this->key)){
      self::$keycount++;
      $this->key= self::$keycount;
    }
    return $this->key;
  }
}

下面將要講到的類別都會繼承這個類,並且他和OperatorExpression(操作符表達式抽象類別)是一個組合的關係,也就是說OperatorExpression在初始化時可以包含所有繼承了Expression的子類別(這也是本書一直在強調的要面向接口編程,這個Expression就是個接口,利用這個接口可以實現多態,不知道自己裝B說的對不對,哈! 具體可以在看看原書的類圖)

三、LiteralExpression 文字表達式類,作用就是將一個字符串保存到InterpreterContext這個小容器裡,保存成一個索引數組,例如儲存開頭那二句自創程式碼中的4 或four

#程式碼如下:


class LiteralExpression extends Expression{
  private $value;  
  function __construct ($value){      //初始化时传入要保存的值
    $this->value= $value;
  }
  function interpret(InterpreterContext $context){    //调用InterpreterContext类的replace()将$value保存到InterpreterContext这个小容器里
    $context->replace($this,$this->value);
  }
}

四、VariableExpression 變數表達式類,和上面類的作用是一樣的只不過資料將被保存成關聯數組,關聯數組中的健是變數名,值呢就是變數的值,例如開頭二句中的變數"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){  //用于设置变量的值
    $this->val = $value;
  }
  
  function getKey(){    //这个复写了父类的getKey()方法,在小容器InterpreterContext的lookup()方法调用这个类的实例的getKey()方法时 它将返回一个字符串(即变量名)而不是数字索引
    return $this->name;
  }
}

五、OperatorExpression 運算子表達式抽象基底類別,這類繼承且組合了Expression抽象基底類別,實作的interpret()方法主要保存表達式的計算結果



她程式碼如下:

abstract class OperatorExpression extends Expression{
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;
}

function interpret(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);  //具体的比较运算由继承的子类来实现
}

protected abstract function doInterpret(InterpreterContext $context,$result_l,$result_r);

}
#六、EqualsExpression、BooleanOrExpression、BooleanAndExpression,分別為繼承了OperatorExpression 抽象基底類別的相等表達式、或表達式、與表達式只有一個方法doInterpret()內部呼叫了InterpreterContext類別的replace()方法將表達式的計算結果保存到InterpreterContext類別的實例中


程式碼如下:

//相等表达式
class EqualsExpression extends OperatorExpression {
protected function doInterpret(InterpreterContext $context,$result_l,$result_r){
$context->replace($this,$result_l == $result_r);
}
}

//或表达式
class BooleanOrExpression extends OperatorExpression{
protected function doInterpret(InterpreterContext $context,$result_l,$result_r){
$context->replace($this,$result_l || $result_r);
}
}


//与表达式
class BooleanAndExpression extends OperatorExpression{
protected function doInterpret(InterpreterContext $context,$result_l,$result_r){
$context->replace($this,$result_l && $result_r);
}
}
到此為止此模式相關的類別就介紹完畢,上述程式碼都是進過測試的,可直接複製貼上運行來查看結果,現在我們就來看看客戶端程式碼:

客戶端程式碼一:

#############
$context = new InterpreterContext();

$statement = new BooleanOrExpression (  //可尝试将此操作符表达式换成BooleanAndExpression 运行一下 看看执行结果

//可尝试将LiteralExpression中实例化的参数改成其他值看看运算结果,或者直接将EqualsExpression对象换成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 '条件不成立';
}
#########客戶端程式碼三:############這是原文的客戶端程式碼實例和上述客戶端程式碼的差別在於使用了變數表達式VariableExpression############
$context = new InterpreterContext();    
$input = new VariableExpression('input');  //这里定义了一个变量input 但并未赋值

$statement = new BooleanOrExpression(
new EqualsExpression($input,new LiteralExpression('four')),  //这里变量表达式和文字表达式的值将进行一个是否相等的比较
new EqualsExpression($input,new LiteralExpression('4'))
);

foreach (array("four","4","52") as $val){
$input->setValue($val);        //对input这个变量赋值
print "变量input的值为:$val:<br/>";
$statement->interpret($context);  //进行比较并将比较结果存入InterpreterContext对象实例
if($context->lookup($statement)){  //获取比较的结果
print "条件成立 <br/>";
} else {
print "条件不成立 <br/>";
}
}

上述代码经过测试都可以正常运行,有需要的朋友可以复制下来,运行一下看看结果。

以上是PHP解釋器模式用法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn