设计模式专题(二十三)——解释器模式
(原创内容,转载请注明来源,谢谢)
一、概述
解释器模式(interpreter)是给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
如果某一特定类型发生的频率足够高,那么就可以将问题的各个实例表述为一个简单语言中的句子,并构建解释器,通过解释句子,解释器来解决问题。
例如字符串匹配,大多数语言用到的正则表达式,就可以理解成一种解释器模式,字符串是待匹配字符的集合,而表达式是一种匹配模式。
当有一个语言需要解释器执行,并且可以将该语言中的句子表示为抽象语法树,则可以使用解释器模式。解释器模式可以容易的改变和扩展文法,由于该模式用类表示文法规则,因此可以继承类来改变文法,也比较容易实现文法。因为定义抽象语法树中各节点的类的实现大体相似,这些类都易于直接编写。
二、类图
三、设计实现
1、设计方案
解释器模式包含以下5个模块:
1)文本类,用于提供文本。
2)解释器抽象类,定义解释器必须的内容。
3)解释器具体类,可以根据实际情况进行解释。
4)工厂类,类图中没有,可以在客户端与解释器抽象类之间加一个工厂类,由工厂类判断该如何调用抽象解释器,这样可以使得修改代码避免修改客户端。
5)客户端代码。
2、设计内容
sql查询的类,可以有各种类型的拼接sql的方式,这里用解释器模式初步实现部分的方法。
这里仅实现两个拼接where语句的类。
原生的是where|and|compare|a|equal|b形式。
1)where(‘and’,’compare’, ’a’, ’equal’, ’b’);表示where a=b或者...and a=b
2)where(‘or’, ‘like’,‘c’, ‘%’, ‘dd’, ‘%’);表示where c like ‘%d%’ 或者… or c like ‘%d%’
3、具体实现
<?php
//解释器模式——模拟where语句
//1.文本类
class Context{
private$rawContents;//翻译前
private$arrMid;//翻译中的临时变量
private$interContents;//翻译后,失败时为##error:msg##
publicfunction __construct($rawStr){
$this->rawContents= $rawStr;
$this->interContents= '';
$this->arrMid= array();
}
publicfunction getRaw(){
return$this->rawContents;
}
publicfunction getInter(){
return$this->interContents;
}
publicfunction getArrMid(){
return$this->arrMid;
}
publicfunction setRaw($rawStr){
$this->rawContents= $rawStr;
}
publicfunction setInter($interStr){
$this->interContents= $interStr;
}
publicfunction setArrMid(array $arr){
$this->arrMid= $arr;
}
}
//2.解释器抽象类
abstract class Interpreter{
protected$result = '';
protected$context;
publicfunction __construct(Context $context){
$this->context= $context;
}
publicfunction setContext(Context $context){
$this->context= $context;
}
publicfunction explain(){}
publicfunction getResult(){
return$this->result;
}
protectedfunction setContextInter($interStr){
$this->context->setInter($interStr);
return$this->context;
}
}
//3.具体解释器1--where的比较解释器
class InterpreterCompare extendsInterpreter{
publicfunction __construct(Context $context){
praent::__construct(Context$context);
}
publicfunction explain(){
$arrMid= $this->context->getArrMid();
if(5!= count($arrMid)){
$this->setContextInter('##error:wrongcompare type##');
}
switch($arrMid[3]) {
case'equal':
$this->result= $arrMid[2] . '=' . $arrMid[4];
$this->setContextInter($this->result);
break;
case'large':
$this->result= $arrMid[2] . '>' . $arrMid[4];
$this->setContextInter($this->result);
default:
$this->setContextInter('##error:wrongcompare node##');
break;
}
return$this->context;
}
}
//4.具体解释器2--where的like解释器
class InterpreterLike extends Interpreter{
publicfunction __construct(Context $context){
praent::__construct(Context$context);
}
publicfunction explain(){
$arrMid= $this->context->getArrMid();
if(6!= count($arrMid)){
$this->setFalse('##error:wrongcompare type##');
}
$this->result= $arrMid[2];
$this->result.= '%' == $arrMid[3] ? '%' : '';
$this->result.= $arrMid[4];
$this->result.= '%' == $arrMid[5] ? '%' : '';
return$this->context;
}
}
//5.工厂类
class InterpreterFactory{
private$arrInters;
private$context;
privatestatic $ins;
privatefunction __construct(){}
privatefunction __clone(){}
publicstatic function getInstance(){
if(null== self::$ins){
self::$ins= new self;
$this->arrInters= array();
$this->context= null;
}
returnself::$ins;
}
publicfunction setContext(Context $context){
$this->context= $context;
return$this;
}
publicfunction doInterpreter(){
$rawStr= $this->context->getRaw();
//原生的是where|and|compare|a|equal|b形式
$rawArr= explode('|', $rawStr);
if('where'!= $rawArr[0] || 6 != count($rawArr)){
return$this->setFalse('##error:wrong raw string##');
}
$this->context->setArrMid($rawArr);//设置中间变量
$interpreterType= $rawArr[2];//compare like
switch($interpreterType) {
case'compare':
if(!isset($this->arrInters['compare'])){
$this->arrInters['compare']= new InterpreterCompare($this->context);
}
$this->context= $this->arrInters['compare']->explain();
break;
case'like':
if(!isset($this->arrInters['like'])){
$this->arrInters['like']= new InterpreterLike($this->context);
}
$this->context= $this->arrInters['like']->explain();
break;
default:
$this->setFalse('##error:wronginterpreter type##');
break;
}
return$this->context;
}
privatefunction setFalse($interStr){
$this->context->setInter($interStr);
return$this->context;
}
}
//6.客户端
$rawStr = 'where|and|compare|a|equal|b';
$rawContext = new Context($rawStr);
$interContext =InterpreterFactory::getInstance()
->setContext($rawContext)
->doInterpreter();
——written by linhxx 2017.08.31
相关阅读: