侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

老生常谈PHP面向对象之解释器模式

php  /  管理员 发布于 7年前   134

最近在看 “深入PHP面向对象模式与实践” ,学习书中的内容后瞬间觉得自己有点高大上了,哈 ! 其实还是个菜B。相信也会有新手朋友在看这本(我自己也是新手),对书中我个人认为比较难的内容的学习心得就想拿出来分享和交流,1是希望对自己所学知识能够起到巩固和加深理解的作用 2是希望对看到本文且感兴趣的新手朋友一些帮助。

这部分内容看了好几遍了代码也跟着敲了几遍,估计本文想要实现的功能大概就是用户在web页面上输入一些内容,然后通过后台程序解析后进行回复(感觉就是在废话)。例如我在前台web页面输入框里输入:

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

然后提交,系统就会回复类似 “条件成立” 或者 “条件不成立”的结果(有点类似直接在前台写代码并运行,后台解析后会返回一个结果。原书中虽然没有讲解整个前台输入到后台解析的过程但我猜这个后台解析应该还有一个使用正则表达式提取类似上面2行代码中关键字的过程)

上面这二行代码虽然是作者发明的语言,但根据字面含义也不难理解,第一行是定义一个变量并赋值,第二行是对变量进行一个判断(变量等于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:
";$statement->interpret($context);  //进行比较并将比较结果存入InterpreterContext对象实例if($context->lookup($statement)){  //获取比较的结果print "条件成立
";} else {print "条件不成立
";}}

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

以上这篇老生常谈PHP面向对象之解释器模式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

您可能感兴趣的文章:

  • thinkPHP中钩子的两种配置调用方法详解
  • thinkPHP中钩子的使用方法实例分析
  • PHP钩子与简单分发方式实例分析
  • thinkPHP基于反射实现钩子的方法分析
  • php面向对象值单例模式
  • PHP面向对象程序设计组合模式与装饰模式详解
  • 老生常谈PHP面向对象之命令模式(必看篇)
  • 老生常谈PHP面向对象之注册表模式
  • PHP面向对象之事务脚本模式(详解)
  • 浅谈PHP面向对象之访问者模式+组合模式
  • PHP钩子实现方法解析


  • 上一条:
    PHP正则+Snoopy抓取框架实现的抓取淘宝店信誉功能实例
    下一条:
    php使用curl实现ftp文件下载功能
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客