欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

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

程序员文章站 2024-01-20 20:06:46
...
声明:本系列博客参考资料《大话设计模式》,作者程杰。

解释器模式:Given a language, define arepresentation for its grammar along with an interpreter that uses therepresentation to interpret sentences in the language。给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。


类图:



角色:

环境角色(PlayContent):定义解释规则的全局信息。

抽象解释器(Empress):定义了部分解释具体实现,封装了一些由具体解释器实现的接口。

具体解释器(MusicNote):实现抽象解释器的接口,进行具体的解释执行。


核心代码:(注意:需要开启extension=php_mbstring.dll扩展)

content))        {            return false;        }        $key=mb_substr($play_content->content,0,1);        $play_content->content=mb_substr($play_content->content,2);        $val=mb_substr($play_content->content,0,mb_strpos($play_content->content,' '));        $play_content->content=mb_substr($play_content->content,mb_strpos($play_content->content,' ')+1);                return $this->Excute($key,$val);    }    public abstract function Excute($key,$val);}//------------------------具体解析器-------------/**音符 * Class MusicNote */class MusicNote extends IExpress{    public function Excute($key,$val)    {        $note="";        switch($key)        {            case "C":                $note = "1";                break;            case "D":                $note = "2";                break;            case "E":                $note = "3";                break;            case "F":                $note = "4";                break;            case "G":                $note = "5";                break;            case "A":                $note = "6";                break;            case "B":                $note = "7";                break;        }        return $note;    }}/**音阶 * Class MusicScale */class MusicScale extends IExpress{    public function Excute($key,$val)    {        $scale="";        switch($val)        {            case "1":                $scale="低音";                break;            case "2":                $scale="中音";                break;            case "3":                $scale="高音";                break;        }        return $scale;    }}

调用客户端代码:

header("Content-Type:text/html;charset=utf-8");//-------------------------解释器模式-------------------------------require_once "./Interpreter/Interpreter.php";$play_content=new PlayContent();$play_content->content="O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ";$interpreter=null;try{    while(!empty($play_content->content))    {        $str = mb_substr($play_content->content,0,1);        switch($str)        {            case "O":                $interpreter = new MusicScale();                break;            case "C":            case "D":            case "E":            case "F":            case "G":            case "A":            case "B":            case "P":                $interpreter = new MusicNote();                break;        }        echo $interpreter->Translate($play_content).'::';    }}catch(Exception $e){    echo $e->getMessage();}

优点:

解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。


缺点:

1.解释器模式会引起类膨胀

2.每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。

3.解释器模式采用递归调用方法

每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断点的调试下去,直到最小的语法单元。

效率问题

解释器模式由于使用了大量的循环和递归,效率是个不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。


适用场景:

1、重复发生的问题可以使用解释器模式

例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,但是非终结符表达式就需要制定了。在这种情况下,可以通过程序来一劳永逸地解决该问题。

2、一个简单语法需要解释的场景

为什么是简单?文法规则越多,复杂度越高,而且类间还要进行递归调用,不是一般地复杂。想想看,多个类之间的调用你需要什么样的耐心和信心去排查问题。因此,解释器模式一般用来解析比较标准的字符集,例如SQL语法分析,不过该部分逐渐被专用工具所取代。

欢迎关注我的视频课程,地址如下,谢谢。


PHP面向对象设计模式