设计模式专题(二十三) ——解释器模式

设计模式专题(二十三)——解释器模式

(原创内容,转载请注明来源,谢谢)

一、概述

解释器模式(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

相关阅读:

设计模式专题(二十二) ——享元模式

设计模式专题(二十一) ——中介者模式

设计模式专题(二十) ——职责链模式

设计模式专题(十九) ——命令模式

设计模式专题(十八) ——桥接模式

设计模式专题(十七) ——单例模式

设计模式专题(十六)——迭代器模式

设计模式专题(十五) ——组合模式

设计模式专题(十四)——适配器模式

设计模式专题(十三) ——备忘录模式

设计模式专题(十二)——状态模式

设计模式专题(十一)——抽象工厂模式

设计模式专题(十)——观察者模式

设计模式专题(九) ——外观模式

设计模式专题(八) ——模板方法模式

设计模式专题(七)——建造者模式

设计模式专题(六)——原型模式

设计模式专题(五)——工厂方法模式

设计模式专题(四)——代理模式

设计模式专题(三)——装饰模式

设计模式专题(二)——策略模式

设计模式专题(一)——面向对象的设计原则

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

JavaSE(十一)之异常处理详解

一、异常概述   在我们日常生活中,有时会出现各种各样的异常,例如:职工小王开车去上班,在正常情况下,小王会准时到达单位。但是天有不测风云,在小王去上班时,可能...

1949
来自专栏蓝天

三年经验的C,超过两题答不出请离开软件界

5.请描述不使用main函数的情况先怎样设置程序入口函数?(描述cl或gcc中的一种)

961
来自专栏lgp20151222

理解一下策略模式,工厂模式

开发遇到了一个工厂模式和策略模式合起来的代码,觉得真的是写的太好了,所以打算了解下这两个模式的区别。

1341
来自专栏吴裕超

es6 常用总结

在ES6之前,我们都是用var关键字声明变量。无论声明在何处,都会被视为声明在函数的最顶部(不在函数的最顶部就在全局作用域的最顶部)。这就是函数变量提升例如:

1664
来自专栏www.96php.cn

PHP关键字、PHP 语言结构(Language constructs)和函数的区别

1、 什么是语言结构和函数 语言结构: 就是PHP语言的关键词,语言语法的一部分; 它不可以被用户定义或者添加到语言扩展或者库中; ...

4029
来自专栏用户2442861的专栏

Java中Synchronized的用法

原文:http://blog.csdn.net/luoweifu/article/details/46613015 作者:luoweifu 转载请标名...

721
来自专栏PHP实战技术

你应该这个姿势学习PHP(1)

  应用场景:能防止sql的注入(当然并不完全是可以,我们可以使用pdo进行预处理然后方式sql的注入,安全不能只靠一种方式防止事情的发生)

52717
来自专栏冰霜之地

从 JavaScript 作用域说开去

在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言...

1033
来自专栏WD学习记录

基本一

1.extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern也可用来进行...

1565
来自专栏互联网杂技

前端--理解 Promise 的工作原理

Javascript 采用回调函数(callback)来处理异步编程。从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的...

3726

扫码关注云+社区

领取腾讯云代金券