PHP面向对象之解释器模式

    在博客园逛了1年多,从来都是看文章但没发表过什么文章。主要是因为技术太菜了,只有学习的份,自己那点水平实在也没什么好去分享的。但是最近在看 “深入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/>";
}
}

上述代码经过测试都可以正常运行,有需要的朋友可以复制下来,运行一下看看结果。最后借用古人的一句话来共勉:"路漫漫其修远兮,吾将上下而求索"!

时间: 2025-01-09 11:21:57

PHP面向对象之解释器模式的相关文章

面向对象编程思想-解释器模式

一.引言 我们常常在会在字符串中搜索匹配字符或判断一个字符串是否符合我们要的格式时,使用正则表达式,可解决问题的背后是一种什么思想呢?即我们今天要学习的内容,解释器模式 二.解释器模式 定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子 1.文法:即语法规则.在解释器模式中每一个语法都对应一个解释器对象,用来处理相应的语法规则.它对于扩展.改变文法规则都很方便 2.可以通过抽象语法树(Abstract Syntax Tree,AST)的图形方式来

面向对象的设计模式(十三),解释器模式

解释器模式,从字面上解释来说就是为一个文法(具有特定语法的形式的语句或表达式)构造解释器,这个解释器用来解释这个文法,使得这样的具有某种书写规则的文法能够表示特定的功能,这样的特定书写规则也就是通常所说的语法,如C/C++,Java,Python等计算机语言有自己的语法.还有,一些解释型语言如Python.它在执行的时候须要Python解释器,这也就是一种解释器. 定义:解释器模式为一些具有特定书写规则的文法编写解释器,从而使得它具有某种意义. 使用场景: 作为解释器. 解释具有特定语法的语句的

行为型模式之解释器模式

概述 解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它用于描述如何使用面向对象语言构成一个简单的语言解释器.在某些情况下,为了更好地描述某一些特定类型的问题,我们可以创建一种新的语言,这种语言拥有自己的表达式和结构,即文法规则,这些问题的实例将对应为该语言中的句子.此时,可以使用解释器模式来设计这种新的语言.对解释器模式的学习能够加深我们对面向对象思想的理解,并且掌握编程语言中文法规则的解释过程 定义 解释器模式(Interpreter Pattern):定义一个语言的文法,并且建立

原始的解释器模式(Interpreter Pattern)

解释器模式的定义(现实项目中很少遇到,因此直接理论先...) 解释器模式是一种按照规定语法进行解析的方案,在现在项目中使用较少,其定义为:给定一门语言,定义它的方法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.其构成如下: 1.AbstractExpression--抽象解释器 具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression和NonterminalExpression完成 2.TerminalExpression--终结符表达式 实现

设计模式--19、解释器模式

定义:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子. 类型:行为类模式 类图: 解释器模式是一个比较少用的模式,本人之前也没有用过这个模式.下面我们就来一起看一下解释器模式. 解释器模式的结构 抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作.具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器Nontermi

PHP设计模式——解释器模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 解释器模式:Given a language, define arepresentation for its grammar along with an interpreter that uses therepresentation to interpret sentences in the language.给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 类图: 角色: 环境角色(Play

(21)解释器模式

(21)解释器模式 定义:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子. 类型:行为类模式 类图: 解释器模式是一个比较少用的模式. 解释器模式的结构 l  抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作.具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成. l

设计模式解密(21)- 解释器模式

1.简介 定义:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子. 主要解决:对于一些固定文法构建一个解释句子的解释器. 本质:分离实现,解释执行.Interpreter模式其实就是一种简单的语法解释器构架. 英文:Interpreter 类型:行为型 2.类图及组成 (引)类图: 组成: AbstractExpression(抽象表达式):定义解释器的接口,约定解释器的解释操作. TerminalExpression(终结符表达式):用来实现语法规则中和

PHP面向对象之策略模式

策略模式按我个人的理解说就是将类中重复使用的代码分离出来形成一个策略类,其他类想要调用的话,首先在初始化的时候就要把这个策略类作为参数传递进来即形成一种组合关系,然后在类内部就可以直接调用这个策略类中的逻辑了. 简单说一下类的组合与聚合关系(很长一段时间里对这种关系一直比较懵,代码看多了,并查看了一些资料才稍微有些概念,这里单独拿出来说一下),类的组合关系类似一个人,人要是死了身体的各个器官就消亡了,这个器官可以理解成上述的策略类.需要调用这个策略类的类假如生命周期结束,那么这个策略类的生命周期