扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这篇文章给大家介绍怎么在PHP项目中实现一个解释器模式,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
专注于为中小企业提供网站建设、成都网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业沾化免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了1000+企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。一、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:
"; $statement->interpret($context); //进行比较并将比较结果存入InterpreterContext对象实例 if($context->lookup($statement)){ //获取比较的结果 print "条件成立
"; } else { print "条件不成立
"; } }
关于怎么在PHP项目中实现一个解释器模式就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流