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

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

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

一、概述

解释器模式(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 条评论
登录 后参与评论

相关文章

来自专栏情情说

深入浅出MyBatis:JDBC和MyBatis介绍

最近在休陪产假,时间比较零碎,准备看2本书充实下,一本是「深入浅出MyBatis:技术原理与实践」,一本是「RabbitMQ实战:高效部署分布式消息队列」,为了...

3188
来自专栏前端黑板报

采用Symbol和process.nextTick实现Promise

作者简介:slashhuang 研究型程序员 现就职于爱屋吉屋 Promise已经成为处理Node.js异步流程的标配技术。 V8的async/await语法构...

2188
来自专栏沈唁志

浅谈PHP中的设计模式

953
来自专栏赵俊的Java专栏

如何理解 Spring 的 IOC 思想?

1423
来自专栏java思维导图

Spring思维导图,让Spring不再难懂(ioc篇)

写在前面 写过java的都知道:所有的对象都必须创建;或者说:使用对象之前必须先创建。而使用ioc之后,你就可以不再手动创建对象,而是从ioc容器中直接获取对象...

3377
来自专栏美团技术团队

Mson,让JSON序列化更快

本文由秦喆 芝任 天洲 赵鹏四位作者共同完成。 问题 我们经常需要在主线程中读取一些配置文件或者缓存数据,最常用的结构化存储数据的方式就是将对象序列化为JSON...

38711
来自专栏阿杜的世界

Java 8中Stream使用的一个小点

之前没仔细查过Stream的源码,也没有深究背后的原因,今天跟了下源码,最后跟到ReferencePipeline#193行,应该是调用apply的时候,入参u...

402
来自专栏社区的朋友们

Java 动态加载 so 的解决方案

业务场景有对 so 实现动态加载/替换的需求,但 Java 并没有直接动态加载 so 的机制。本文将深度剖析 Java 加载 so 的实现机制,并提出一套 Ja...

8351
来自专栏青玉伏案

代码重构(五):继承关系重构规则

陆陆续续的发表了多篇关于重构的文章了,还是那句话,重构是一个项目迭代开发中必不可少的一个阶段。其实重构伴随着你的项目的整个阶段。在前几篇关于重构的文章中我们谈到...

1796
来自专栏决胜机器学习

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

设计模式专题(十七)——单例模式 (原创内容,转载请注明来源,谢谢) 一、概述 单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访...

2987

扫描关注云+社区