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

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

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

一、概述

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

相关文章

来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4848
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

25310
来自专栏hbbliyong

WPF Trigger for IsSelected in a DataTemplate for ListBox items

<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}"> <vw:HeaderSlug...

4064
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2152
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2645
来自专栏跟着阿笨一起玩NET

c#实现打印功能

2752
来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

3859
来自专栏魂祭心

原 canvas绘制clock

4064
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

2707

扫码关注云+社区