全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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

最近在看 “深入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:<br/>";
$statement->interpret($context);  //进行比较并将比较结果存入InterpreterContext对象实例
if($context->lookup($statement)){  //获取比较的结果
print "条件成立 <br/>";
} else {
print "条件不成立 <br/>";
}
}

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

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


# php  # 解释器模式  # PHP设计模式之解释器模式的深入解析  # php设计模式 Interpreter(解释器模式)  # PHP设计模式之解释器模式浅析  # 子类  # 客户端  # 书中  # 不成立  # 就会  # 是个  # 就像  # 给大家  # 变量名  # 继承了  # 面向对象  # 都是  # 是一个  # 这是  # 会有  # 我在  # 看了  # 容器里  # 本书  # 抽象类 


相关文章: 建站之星安装模板失败:服务器环境不兼容?  建站之星2.7模板快速切换与批量管理功能操作指南  成都网站制作报价公司,成都工业用气开户费用?  网站建设设计制作营销公司南阳,如何策划设计和建设网站?  制作网站公司那家好,网络公司是做什么的?  常州企业网站制作公司,全国继续教育网怎么登录?  岳西云建站教程与模板下载_一站式快速建站系统操作指南  定制建站模板如何实现SEO优化与智能系统配置?18字教程  建站之星2.7模板:企业网站建设与h5定制设计专题  如何在万网主机上快速搭建网站?  威客平台建站流程解析:高效搭建教程与设计优化方案  韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐  C#如何在一个XML文件中查找并替换文本内容  实现虚拟支付需哪些建站技术支撑?  在线制作视频的网站有哪些,电脑如何制作视频短片?  如何通过服务器快速搭建网站?完整步骤解析  浅析上传头像示例及其注意事项  建站之星各版本价格是多少?  c# Task.ConfigureAwait(true) 在什么场景下是必须的  网站制作软件免费下载安装,有哪些免费下载的软件网站?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  c# 服务器GC和工作站GC的区别和设置  唐山网站制作公司有哪些,唐山找工作哪个网站最靠谱?  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  建站VPS选购需注意哪些关键参数?  已有域名和空间,如何快速搭建网站?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  如何在IIS中新建站点并配置端口与IP地址?  可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?  宝塔Windows建站如何避免显示默认IIS页面?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  微信推文制作网站有哪些,怎么做微信推文,急?  建站主机选购指南与交易推荐:核心配置解析  高端网站建设与定制开发一站式解决方案 中企动力  代刷网站制作软件,别人代刷火车票靠谱吗?  湖北网站制作公司有哪些,湖北清能集团官网?  专业网站制作服务公司,有哪些网站可以免费发布招聘信息?  电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  建站之星安装后界面空白如何解决?  广州建站公司哪家好?十大优质服务商推荐  小型网站制作HTML,*游戏网站怎么搭建?  网站制作费用多少钱,一个网站的运营,需要哪些费用?  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  如何获取上海专业网站定制建站电话?  浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?  企业宣传片制作网站有哪些,传媒公司怎么找企业宣传片项目?  如何选择美橙互联多站合一建站方案? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。